{x} {expr $x*$x}One may assign such values to a variable (or array element), or pass them around by value:
set sq {{x} {expr $x*$x}}To "run" a lambda, to make it execute like a Tcl command, the first take is an explicit apply:}
proc apply {lambda args} { foreach {argl body} $lambda break if {[llength $argl] != [llength $args]} { error "argument mismatch, expected $argl" } foreach $argl $args break if 1 $body }if 0 {Testing:
% set sq {x {expr {$x*$x}}} x {expr {$x*$x}} % apply $sq 5 25But to prefix each lambda invocation with apply seems like back in the dark (Fortran CALL, Basic GOSUB) ages... So let's see how to get Tcl to call apply automatically when meeting a lambda. Lambdas are lists of two elements, so if we assert that "normal" command names do not contain exactly one space, we can extend unknown to apply commands whose name happens to be a list of length 2: }
proc unknown args [string map [list @ [info body unknown]] { if {[llength [lindex $args 0]]==2} { return [uplevel 1 apply $args] } @}]if 0 {Now we can call our lambdas by given name:
% $sq 5 25or, if we don't bother picking a name, by explicit specification:
% {x {expr sqrt($x)}} 25 5.0The drawback is that the lambda body goes through eval every time, so is slower than a byte-compiled proc body. On the other hand, we don't have to worry about garbage, as local variables are disposed of automatically - and we finally have real local procedures... }
DKF - Another possibility is to use the auto-expanding unknown also used in Hot Curry and to create the lambda "function" with apply pre-applied:
proc lambda {arguments body} { return [list apply [list $arguments $body]] }I always prefer to use a mechanism that is useful in more than one way. :^) RS: Yes - my original proposal had the drawback of conflicting semantics for unknown (if used together with Hot curry). Your change is indeed better.