expr* arg ?arg arg ...?


expr* evaluates each of its arguments with expr and returns the list of results.

expr* with a single argument yields the same result as expr with a single argument.


proc expr* args {lmap e $args {uplevel 1 [list expr $e]}}

With tailcall:

proc expr* args {tailcall lmap ___e $args {expr $___e}}

Implementations by dkf. Idea offered by LEG as one of the responses to the perennial expr discussion in 2023.


expr* differs from expr by its interface. expr concats it's arguments and evaluates the result in it's own little language. This can lead to unwanted results via double substitution. For standard usage and beginners it is recommended to always brace your expr-essions, resulting in general usage of a single argument for expr.

expr* requires each expression to be braced or quoted anyway.

Several quests and TIPs evolve around the perceived unhandyness of expr in certain situations. I contend that some of them can be helped by expr*'s different interface.

Example, taken from the chat: canvas operations involve specification of coordinate lists:

.canvas create rectangle [expr {$w-100}] [expr {$h-40}] [expr {$w+100}] [expr {$h+40}]

With expr*:

.canvas create rectangle {*}[expr* {$w-100} {$h-40} {$w+100} {$h+40}]

Note: the same with mathop:

.canvas create rectangle [- $w 100] [- $h 40] [+ $w 100] [+ $h 40]