**How to quickly write TCL procs with switches and the like?** This is a proposal on how to extend the notation of args in the definition of proc. It is a request for comments, no implementation is available now. ***What types of args / switches shall be available?*** 1. switches with values, e.g. '''-start''' ''index'' of [lsearch]; they do have a default value 2. switches without value, e.g. '''-exact''' of [lsearch]; their existence is boolean, false by default 3. required named parameters 4. optional named parameters with default values 5. unnamed optional parameters ***How shall these parameters be accessed inside the procedure?*** Numbered as above... 1. switches could be just local variables, e.g. ${-start} 2. boolean values of local variables, e.g. ${-exact} 3. this is the default 4. just like the original implementation 5. ''args'' is still available to catch the rest ***Suggestion*** Allow extended syntax of ''args'': This special parameter name comes as a list... * first item is the keyword ''args'' * items with leading dash are boolean switches (with (1.) or without (2.) default values) * items without leading dash are named parameters (with (3.) or without (4.) default values) * items that are a list of two elements are the name and the default value respectively * the last item can optionally be ''args'' again (5.) ***Example*** Assume an extension to [subst]: ====== proc mysubst {{args -nobackslashes -nocommands -novariables -nocomplain {-uplevel 0} -inplace string1 {string2 {}} args}} { # the above notation is backward compatible ("default values" of args are currently ignored). # a redirection of proc could generate the following code: set -nobackslashes false set -nocommands false set -novariables false set -nocomplain false set -uplevel 0 set -inplace false set string2 {} for {set i 0} {$i < 7} {incr i} { # 7 is the max number of switches plus their values set c [lindex $args $i] if {$c in {-uplevel}} { # 1. switches with default values set $c [lindex $args [incr i]] } elseif {$c in {-nobackslashes -nocommands -novariables -nocomplain -inplace}} { # 2. boolean switches set $c true } else { if {$c eq {--}} {incr i} break } } incr i -1 ;# or do not incr in the first line below (which is harder to generate)? # 3. required (consider errors!) set string1 [lindex $args [incr i]] # 4. optional if {[llength $args] > [incr i]} {set string2 [lindex $args $i]} # more of the above line can be nested in the then-branch... # 5. unnamed set args [lrange $args $i end] unset i c # end of generated code - body below # relative levels are offset by one catch {incr -uplevel} # having both string and args is just to demonstrate the possibilities - use args only if {{} eq $string2} {set args $string1} {set args [list $string1 $string2 {*}$args]} # TODO implement # something like the following - use catch if -nocomplain and return unmodified # also, if -inplace use upvar 1 and modify the values; plus consider a loop for args... # return [uplevel ${-uplevel} [list ::subst {*}$forward_switches $string]] # demo output foreach var {-nobackslashes -nocommands -novariables -nocomplain -uplevel -inplace string1 string2 args} { puts "$var is {[set $var]}" } } ====== ====== set x 14 set y {$x} set z {[expr $x * 3]} subst -nocomplain -inplace x y z ====== ***Considerations*** * the double-dash "--" is always a good idea to protect non-switches starting with a dash * implementation could happen as proc-redirection or even better natively (just like the interpreter handles optional parameters now!) * should the generated code be visible in [info body]? * the above generated code does not allow parameters with names ''c'' or ''i''. * parameters are switches if and only if their name starts with a dash <> Argument Processing