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 <[EMAIL PROTECTED]> 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
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel
--
Vlad Seryakov
571 262-8608 office
[EMAIL PROTECTED]
http://www.crystalballinc.com/vlad/