From: <vl...@cr...> - 2005-05-28 21:02:51
|
I like this but can it be list instead of oneof<br /> <br /> ns_proc connect {{-eightbit flag} {{-speed list {1200 2400 4800}} 4800} {port /dev/ttya}}<br /> <br /> <br /> -------- Original Message -------- To: nav...@li... From: Zoran Vasiljevic Subject: Re: [naviserver-devel] ns_parseargs example Am 27.05.2005 um 18:44 schrieb Stephen Deasey: > Right, but the option list is type checking. One of the syntaxes we > talked about was: > > ns_parseargs {-a:int -b:bool -s:switch} $args > Which seems really as the only meaningful, simple and easy way to do this, I must admit, after thinking awhile. So: ns_parseargs {{-varname?:type? ?default?} ...} where -varname is going to set the variable "varname" and it will first check, according to the ?:type? what it gets. The best is to make some examples: -option would expect an argument and set "option" to argument value and if the -option is not given, will do nothing -option default if option is given, it will take it, otherwise will set the default value -option:flag if the option is given it will set it to the boolean true, otherwise to boolean false -option:oneof {a b c} if the option is given it will check the argument for being one of the a, b or c and set the variable accordingly. Alternatively, one could use lists instead of ":" like this: {-option flag} {-option oneof {a b c}} This is more Tcl-like and allows you freedom in the variable name. Example: ns_proc connect {{-eightbit flag} {{-speed oneof {1200 2400 4800}} 4800} {port /dev/ttya}} { # ... } So I can say: connect and it will use 7bit comm, will take speed 4800 to connect to / dev/ttya connect /dev/ttyb as above but will connect to /dev/ttyb connect -speed 2400 /dev/ttyb as above but will use 2400bps instead of 4800bps connect -speed 9600 /dev/ttyc will throw error connect -eightbit /dev/ttyc will use 8bit comm to connect to /dev/ttyc Apart from "flag" and "oneof" we can later introduce "int", "bool", "wide" etc in order to additionaly check the given value: {{-number_of_retries int} 4} Will expect number_of_retries to be an interger and if not given will set it to 4. What do you think? Zoran  |
From: Zoran V. <zv...@ar...> - 2005-05-28 21:12:48
|
Am 28.05.2005 um 21:01 schrieb vl...@cr...: > I like this but can it be list instead of oneof > > ns_proc connect {{-eightbit flag} {{-speed list {1200 2400 4800}} > 4800} {port /dev/ttya}} > Of course it can. But Stephen is not very optimistic about the syntax altogether... I'm afraid we do not have very much options about all that. Either we drop the type checking and therefore accept no flag-type arguments or similar, or we do something like above and be faced with more complex writing. Zoran |
From: Stephen D. <sd...@gm...> - 2005-05-30 10:24:02
|
On 5/28/05, Zoran Vasiljevic <zv...@ar...> wrote: >=20 > Am 28.05.2005 um 21:01 schrieb vl...@cr...: >=20 > > I like this but can it be list instead of oneof > > > > ns_proc connect {{-eightbit flag} {{-speed list {1200 2400 4800}} > > 4800} {port /dev/ttya}} > > >=20 > Of course it can. But Stephen is not very optimistic > about the syntax altogether... Well, the above example is wrong. It should be: ns_proc connect {{{-eightbit flag}} {{-speed list ... Nested lists are clearly unusable. > I'm afraid we do not have very much options about all that. > Either we drop the type checking and therefore accept no > flag-type arguments or similar, or we do something like above > and be faced with more complex writing. The other option is -eightbit:flag syntax. It's not perfect, but it's better than nested lists and has ~5 years of usage in the ACS behind it. |
From: Zoran V. <zv...@ar...> - 2005-05-30 11:22:28
|
Am 30.05.2005 um 12:23 schrieb Stephen Deasey: > On 5/28/05, Zoran Vasiljevic <zv...@ar...> wrote: > > > > Well, the above example is wrong. It should be: > > ns_proc connect {{{-eightbit flag}} {{-speed list ... > > Nested lists are clearly unusable. They are, indeed, but this is the price for being flexible. > > > >> I'm afraid we do not have very much options about all that. >> Either we drop the type checking and therefore accept no >> flag-type arguments or similar, or we do something like above >> and be faced with more complex writing. >> > > > The other option is -eightbit:flag syntax. It's not perfect, but it's > better than nested lists and has ~5 years of usage in the ACS behind > it. Hm... what I do not like about that is: this is a usage convention and this convention is against the syntax of the language. Maybe this "against" is too harsh word for it, but still... As I said many times before, I think that we are going little bit too far with that. If we just accept the status-quo then we'd have to live without optional flags (and other types of checking), that is, one should/could use: ns_parseargs {{-option true} args} and write like this: -option true -option 1 -option yes -option no etc and internally typecheck: [string is boolean $option]. Nothing will prevent somebody to "-option foo" but this is then in the responsibility of the programmer. Since Tcl does not enforce type-checking, we should not do this either, if it can't coexist peacefully with the language-syntax. Personally, I'd have nothing against if you add this type of parsing but I believe I will not be able to use it. If you think this is widely accepted (I have no such experience so far) then go ahead; I won't stay in the way. Cheer's Zoran > > > ------------------------------------------------------- > This SF.Net email is sponsored by Yahoo. > Introducing Yahoo! Search Developer Network - Create apps using Yahoo! > Search APIs Find out how you can build Yahoo! directly into your own > Applications - visit http://developer.yahoo.net/?fr=offad-ysdn-ostg- > q22005 > _______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel > |
From: Zoran V. <zv...@ar...> - 2005-05-30 19:02:01
|
Am 30.05.2005 um 12:23 schrieb Stephen Deasey: > > The other option is -eightbit:flag syntax. It's not perfect, but it's > better than nested lists and has ~5 years of usage in the ACS behind > it. > Another try (I can't just let go) ... I do not see much sense in trying to keep the Tcl argument list format under all costs. Give me a good reason why we should do that? Anyways, we are about to define a new "proc"-type of command (ns_proc) aren't we? What is the sense then to force ourselves to the old format? Why don't we *extend* Tcl-proc arg-treatment like this: {name typecheck ?default_value?} This is *not* Tcl-proc compatible but *is* in the spirit of the language. The "typecheck" above can/will be definitely a list of one or more elements, depending on the check itself. The typecheck is *forced*. You must give a type. If you need no checking at all use "string" which will cover all possiblities. By *forcing* the type-check, many of the programming errors and double-checks in the procedure itself can be saved. Also, all people needing no extra checking can always use plain Tcl-proc calls. Others who'd need checking would use exteneded ns_proc syntax. This is pretty clear and I see no problems with that at all. For example: ns_parseargs {{-retries int 0} {-blockcopy flag} {device string} args} or ns_proc dosomething {{-retries int 0} {-blockcopy flag} {device string}} { # ... } The most natural Tcl-way is to use lists. We've seen that the desperate try to keep the Tcl-proc syntax leads to too complicated nested lists which humans are not easily assembling. So, this is a plain list which is easy to write and read by humans. We can evolve typecheck over time to include more elaborate tests, but a handful of those (string, int, flag, bool, list) are most useful and complete for about all the needs I can think of at the moment. What is wrong with that (except that it perhaps does not follow openacs model)? Zoran |
From: Stephen D. <sd...@gm...> - 2005-06-01 11:24:15
|
On 5/30/05, Zoran Vasiljevic <zv...@ar...> wrote: >=20 > Am 30.05.2005 um 12:23 schrieb Stephen Deasey: >=20 > > > > The other option is -eightbit:flag syntax. It's not perfect, but it's > > better than nested lists and has ~5 years of usage in the ACS behind > > it. > > >=20 > Another try (I can't just let go) ... >=20 > I do not see much sense in trying to keep the Tcl argument list > format under all costs. Give me a good reason why we should do that? > Anyways, we are about to define a new "proc"-type of command > (ns_proc) aren't we? What is the sense then to force ourselves > to the old format? >=20 > Why don't we *extend* Tcl-proc arg-treatment like this: >=20 > {name typecheck ?default_value?} >=20 > This is *not* Tcl-proc compatible but *is* in the spirit of > the language. The "typecheck" above can/will be definitely > a list of one or more elements, depending on the check itself. > The typecheck is *forced*. You must give a type. If you need > no checking at all use "string" which will cover all possiblities. > By *forcing* the type-check, many of the programming > errors and double-checks in the procedure itself can be saved. >=20 > Also, all people needing no extra checking can always use plain Tcl-proc > calls. Others who'd need checking would use exteneded ns_proc syntax. > This is pretty clear and I see no problems with that at all. >=20 > For example: > ns_parseargs {{-retries int 0} {-blockcopy flag} {device string} > args} >=20 > or > ns_proc dosomething {{-retries int 0} {-blockcopy flag} {device > string}} { > # ... > } >=20 > The most natural Tcl-way is to use lists. We've seen that the > desperate try to keep the Tcl-proc syntax leads to too complicated > nested lists which humans are not easily assembling. > So, this is a plain list which is easy to write and read by humans. >=20 > We can evolve typecheck over time to include more elaborate > tests, but a handful of those (string, int, flag, bool, list) are most > useful and complete for about all the needs I can think of > at the moment. >=20 > What is wrong with that (except that it perhaps does not follow > openacs model)? ns_proc test {{-flag f}} { if {$flag} { ns_log notice ok } } test -flag t ;# ok test -flag true ;# ok test -flag yes ;# ok test -flag 1 ;# ok The result of the expression passed to Tcl's if is converted to boolean so there's no need to use [string is true $x]. The difference between '-flag' and '-flag t' is two characters -- I don't think it's worth it. As I mentioned before, in general I think it's a bad idea to create boolean flags as it makes it cumbersome to call such a proc where the flag is computed. e.g.: if {$x} { foo -flag ... } else { foo ... } It gets really ugly when there are multiple flags. I added boolean flags to the C implementation as there is already existing code which uses them which could benefit from the arg parsing. Regarding the 'oneof' type, maybe what's actually needed is some syntactic sugar? e.g. something like: proc assert_oneof {varname list} { upvar $varname x if {![lsearch -exact $list $x]} { error "assertion failed: $varname must be one of $list" } } proc test {{x foo}} { assert_oneof x {foo bar baz} ... } The disadvantage of extending the proc syntax as you've suggested above is that users are then forced to always provide a type, even if it's just the 'null' type, string. This kind of type checking is likely to be the exception rather than the rule, but I imagine option parsing will be quite common. The ordering of the default argument has changed which is incompatible with what the programmer expects from standard proc usage, even if the mechanical incompatibility does not matter. The oneof check shows that things will get more complicated than simple 'is int', 'is bool' checks. Min and max range checks on integers would be nice, regexp checks on strings would be cool etc... What about applying more than one check to an arg? There would need to be syntax for it as you can't specify the arg more than once as you can specify multiple assertions. Other languages solve this with assertions or pre-conditions and post-conditions, and that feels more like what we're doing here. Tcl *does* have type checking: an integer argument passed to a proc which is then passed to the expr command will cause a conversion failure if the value is 'foo'. The type checking on the proc argument will just cause the failure earlier (and will result in double-checking). What we're catching here are programmer errors. Checking is more urgently required for malicious attacks. You really want to be able to say something like: ns_queryget -assert int -- life 42 It was always in the back of my mind that we needed some kind of unified checking mechanism to handle both procs and ns_queryget (and forms, as in Vlad's nstk). Rather than shoe-horn the type checking of proc into the proc args, perhaps it would be better to use something more direct like the assertion example above? You could imagine various type of syntactic sugar: assert x oneof {foo bar baz} assert { x int y digit } ... Type checking happens at compile time in many languages which makes them better than assertions, but that doesn't apply here. So, how about assertions? |
From: Vlad S. <vl...@cr...> - 2005-06-01 13:48:17
|
To be as much close to current Tcl convention in proc syntax we can add optional type AFTER default value ns_proc test { {-flag 0 flag} {-list a oneof {a b c}} {-name ""} { value "" } } { } This way i do not have to remember 2 different ways to provide default value and if i want type checking, i will give optional typoe, if not then no type cheking. Stephen Deasey wrote: > On 5/30/05, Zoran Vasiljevic <zv...@ar...> wrote: > >>Am 30.05.2005 um 12:23 schrieb Stephen Deasey: >> >> >>>The other option is -eightbit:flag syntax. It's not perfect, but it's >>>better than nested lists and has ~5 years of usage in the ACS behind >>>it. >>> >> >>Another try (I can't just let go) ... >> >>I do not see much sense in trying to keep the Tcl argument list >>format under all costs. Give me a good reason why we should do that? >>Anyways, we are about to define a new "proc"-type of command >>(ns_proc) aren't we? What is the sense then to force ourselves >>to the old format? >> >>Why don't we *extend* Tcl-proc arg-treatment like this: >> >> {name typecheck ?default_value?} >> >>This is *not* Tcl-proc compatible but *is* in the spirit of >>the language. The "typecheck" above can/will be definitely >>a list of one or more elements, depending on the check itself. >>The typecheck is *forced*. You must give a type. If you need >>no checking at all use "string" which will cover all possiblities. >>By *forcing* the type-check, many of the programming >>errors and double-checks in the procedure itself can be saved. >> >>Also, all people needing no extra checking can always use plain Tcl-proc >>calls. Others who'd need checking would use exteneded ns_proc syntax. >>This is pretty clear and I see no problems with that at all. >> >>For example: >> ns_parseargs {{-retries int 0} {-blockcopy flag} {device string} >>args} >> >>or >> ns_proc dosomething {{-retries int 0} {-blockcopy flag} {device >>string}} { >> # ... >> } >> >>The most natural Tcl-way is to use lists. We've seen that the >>desperate try to keep the Tcl-proc syntax leads to too complicated >>nested lists which humans are not easily assembling. >>So, this is a plain list which is easy to write and read by humans. >> >>We can evolve typecheck over time to include more elaborate >>tests, but a handful of those (string, int, flag, bool, list) are most >>useful and complete for about all the needs I can think of >>at the moment. >> >>What is wrong with that (except that it perhaps does not follow >>openacs model)? > > > > ns_proc test {{-flag f}} { > if {$flag} { > ns_log notice ok > } > } > > test -flag t ;# ok > test -flag true ;# ok > test -flag yes ;# ok > test -flag 1 ;# ok > > The result of the expression passed to Tcl's if is converted to > boolean so there's no need to use [string is true $x]. The > difference between '-flag' and '-flag t' is two characters -- I don't > think it's worth it. > > As I mentioned before, in general I think it's a bad idea to create > boolean flags as it makes it cumbersome to call such a proc where the > flag is computed. e.g.: > > if {$x} { > foo -flag ... > } else { > foo ... > } > > It gets really ugly when there are multiple flags. I added boolean > flags to the C implementation as there is already existing code which > uses them which could benefit from the arg parsing. > > > Regarding the 'oneof' type, maybe what's actually needed is some > syntactic sugar? e.g. something like: > > proc assert_oneof {varname list} { > upvar $varname x > if {![lsearch -exact $list $x]} { > error "assertion failed: $varname must be one of $list" > } > } > > proc test {{x foo}} { > assert_oneof x {foo bar baz} > ... > } > > > The disadvantage of extending the proc syntax as you've suggested > above is that users are then forced to always provide a type, even if > it's just the 'null' type, string. This kind of type checking is > likely to be the exception rather than the rule, but I imagine option > parsing will be quite common. The ordering of the default argument > has changed which is incompatible with what the programmer expects > from standard proc usage, even if the mechanical incompatibility does > not matter. > > The oneof check shows that things will get more complicated than > simple 'is int', 'is bool' checks. Min and max range checks on > integers would be nice, regexp checks on strings would be cool etc... > > What about applying more than one check to an arg? There would need > to be syntax for it as you can't specify the arg more than once as you > can specify multiple assertions. > > Other languages solve this with assertions or pre-conditions and > post-conditions, and that feels more like what we're doing here. Tcl > *does* have type checking: an integer argument passed to a proc which > is then passed to the expr command will cause a conversion failure if > the value is 'foo'. The type checking on the proc argument will just > cause the failure earlier (and will result in double-checking). > > What we're catching here are programmer errors. Checking is more > urgently required for malicious attacks. You really want to be able > to say something like: > > ns_queryget -assert int -- life 42 > > It was always in the back of my mind that we needed some kind of > unified checking mechanism to handle both procs and ns_queryget (and > forms, as in Vlad's nstk). Rather than shoe-horn the type checking of > proc into the proc args, perhaps it would be better to use something > more direct like the assertion example above? You could imagine > various type of syntactic sugar: > > assert x oneof {foo bar baz} > > assert { > x int > y digit > } > > ... > > Type checking happens at compile time in many languages which makes > them better than assertions, but that doesn't apply here. So, how > about assertions? > > > ------------------------------------------------------- > This SF.Net email is sponsored by Yahoo. > Introducing Yahoo! Search Developer Network - Create apps using Yahoo! > Search APIs Find out how you can build Yahoo! directly into your own > Applications - visit http://developer.yahoo.net/?fr_______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel -- Vlad Seryakov 571 262-8608 office vl...@cr... http://www.crystalballinc.com/vlad/ |
From: Zoran V. <zv...@ar...> - 2005-06-01 17:16:57
|
Am 01.06.2005 um 15:45 schrieb Vlad Seryakov: > To be as much close to current Tcl convention in proc syntax we can > add optional type AFTER default value > > ns_proc test { {-flag 0 flag} {-list a oneof {a b c}} {-name ""} > { value "" } } { > } > > This way i do not have to remember 2 different ways to provide > default value and if i want type checking, i will give optional > typoe, if not then no type cheking. The only side-effect is of course that you'd need to give the default argument if you need type-checking. I believe I can live with that. Zoran |
From: Zoran V. <zv...@ar...> - 2005-06-01 17:48:23
|
Am 01.06.2005 um 13:24 schrieb Stephen Deasey: > So, how > about assertions? > Good. So, that means we scratch the idea of putting it in the proc/ns_proc syntax and keep it as is, i.e. we parse-out only the options from the argument list and do no extra type checking there. Type-checking would be implemented as a separate command then. I understand the blues with the boolean arguments and I am willing to scratch them from the specs. So, if you need "-dothat" you'd be actually saying "-dothat true" or "-dothat false". All that leaves us with the ns_parseargs pretty much as it is now, or? Apropos assertions: http://www.tcl.tk/cgi-bin/tct/tip/53.html This was withdrawn because of the fact that it already exist in tcllib. So, there is very little to do except "package req tcllib" and use what's there. Zoran |
From: Stephen D. <sd...@gm...> - 2005-06-01 19:30:27
|
On 6/1/05, Zoran Vasiljevic <zv...@ar...> wrote: >=20 > Am 01.06.2005 um 13:24 schrieb Stephen Deasey: >=20 > > So, how > > about assertions? > > >=20 > Good. >=20 > So, that means we scratch the idea of putting it in the > proc/ns_proc syntax and keep it as is, i.e. we parse-out > only the options from the argument list and do no extra > type checking there. Type-checking would be implemented > as a separate command then. >=20 > I understand the blues with the boolean arguments and > I am willing to scratch them from the specs. So, if you > need "-dothat" you'd be actually saying "-dothat true" > or "-dothat false". >=20 > All that leaves us with the ns_parseargs pretty much as > it is now, or? >=20 > Apropos assertions: > http://www.tcl.tk/cgi-bin/tct/tip/53.html >=20 > This was withdrawn because of the fact that it already > exist in tcllib. So, there is very little to do except > "package req tcllib" and use what's there. Looks good. For program bug detection, use tcllib assertions in cooperation with the option parsing we have now. For input validation, some other mechanism should be used. |
From: Zoran V. <zv...@ar...> - 2005-06-01 20:12:55
|
Am 01.06.2005 um 21:30 schrieb Stephen Deasey: > For input > validation, some other mechanism should be used. > Input of what kind? From Tcl or from C? Do you mean form-input? Why you can't apply the tcllib assertion on form-input, if this is what you mean? Zoran |
From: Stephen D. <sd...@gm...> - 2005-06-01 20:23:34
|
On 6/1/05, Zoran Vasiljevic <zv...@ar...> wrote: >=20 > Am 01.06.2005 um 21:30 schrieb Stephen Deasey: >=20 > > For input > > validation, some other mechanism should be used. > > >=20 > Input of what kind? From Tcl or from C? > Do you mean form-input? Why you can't apply the > tcllib assertion on form-input, if this is what you mean? One of the features of tcllib assertions is that you can turn them off, or into no-ops when in production mode, just like standard C assertions. That's a useful feature, but not when you're checking form input! |
From: Zoran V. <zv...@ar...> - 2005-06-01 20:29:31
|
Am 01.06.2005 um 22:23 schrieb Stephen Deasey: > That's a useful feature, but not when you're checking > form input! Why not? |
From: Stephen D. <sd...@gm...> - 2005-06-01 20:50:32
|
On 6/1/05, Zoran Vasiljevic <zv...@ar...> wrote: >=20 > Am 01.06.2005 um 22:23 schrieb Stephen Deasey: >=20 > > That's a useful feature, but not when you're checking > > form input! >=20 > Why not? Because form input always needs to be checked. You can't declare it debugged and turn off exception checking. People will continue to feed your program broken/malicious input. |
From: Zoran V. <zv...@ar...> - 2005-06-01 21:02:10
|
Am 01.06.2005 um 22:50 schrieb Stephen Deasey: > > Because form input always needs to be checked. You can't declare it > debugged and turn off exception checking. People will continue to > feed your program broken/malicious input. > Ah, this is what you mean! What about fixing tcllib to allow two types of asserts? The one with off/on switch and the one without? I haven't looked into there, but this can't be rocket science. Zoran |