AMB:
Based on discussions on the pages Expanding the Expansion Prefix and expr*, I created a small Tcl package called "exprstar" that introduces a modified form of the expr command that returns multiple arguments, separated by commas in the same fashion as inputs to a Tcl math function.
Here is the Github repository: https://github.com/ambaker1/exprstar
The example from the page expr* that demonstrates how using expr can be awkward is as follows:
.canvas create rectangle [expr {$w-100}] [expr {$h-40}] [expr {$w+100}] [expr {$h+40}]
With the expr* command, you can do the following, which makes it a lot more readable.
.canvas create rectangle {*}[expr* {$w-100, $h-40, $w+100, $h+40}]
This also allows you to easily write procs that process arguments in comma-delimited fashion with the expr language.
proc sum {args} { ::tcl::mathop::+ {*}[uplevel 1 expr* $args] } set x 5.0 set y 10.0 sum {$x,$y,$x*$y}; # 65.0
Edit: I was trying out argparse, and realized that you can combine it with expr* to introduce a totally different way of using Tcl:
# func package require exprstar package require argparse proc func {name args} { if {[llength $args] < 2} { return -code error "wrong # args: should be \"func name ?switches? argList body\"" } set switches [lrange $args 0 end-2] if {[lindex $switches end] eq "--"} { set switches [lrange $switches 0 end-1] } if {"-inline" in $switches} { return -code error "-inline switch not supported" } set argList [lindex $args end-1] set body [lindex $args end] tailcall proc $name {args} " set args \[uplevel 1 expr* \$args\] argparse $switches -- {$argList}\n$body" } func perimeter -help {Perimeter of a rectangle} -validate { num {[string is double -strict $arg]} } { {-height= -validate num -default 3.0} {-width= -validate num -default 4.0} } { expr {2*($height + $width)} } set ft 12.0 puts [perimeter {"-h", 10*$ft, "-w", 20*$ft}]; # 720.0 perimeter {"-help"}
This prints out the following message:
720.0 Perimeter of a rectangle. Can accepts unambiguous prefixes instead of switches names. Accepts switches only before parameters. Switches: -height - Expects argument. Default value is 3.0. -width - Expects argument. Default value is 4.0. -help - Help switch, when provided, forces ignoring all other switches and parameters, prints the help message to stdout, and returns up to 2 levels above the current level.
FM. Well, I would prefer to keep, as much as it's possible, the same syntax at the Tcl parser level, because it shall be very generic. I won't like, in a general fashion, to have to quote my arguments, to brace it, or to separate them with comma... The syntax of expr can be more specific, since this command is made for mathematic calculations. That justifiy a more strict syntax at this level.
But, let me continue the ideas I suggest on this matter in the « Expanding the Expansion Prefix » page for an illustration of what I mean :
# We register a "prefixed" annotation specifically on the '''second''' proc argument # It will simply allow any prefix attach to an argument to be set as local variable whose value will be the argument value. # Pseudo-code : interp prefix register -command proc -argument 2 -prefix "prefixed" {args { foreach a $args { set [info annotation $a] $a } }} # Thereafter, we can use this specification in the definition of the perimeter proc proc perimeter {prefixed}{height width} { if {[string is double $height] && [string is double $width]} { return {=}2*$height*$width } else { error "type mismatch" } } # Finaly we can use the proc, by composition of prefix set ft 12 perimeter {{height}=}10*$ft {{width}=}20*$ft
Focus on prefix composition algorithm :