lambda in tcl8.5

As of tcl8.5, Tcl has native support for lambda, provided by means of apply per TIP 194 [L1 ].

The apply command is documented here https://www.tcl-lang.org/man/tcl8.5/TclCmd/apply.htm

This enables the following:

   proc lambda {arglist body {ns {}}} {
     list ::apply [list $arglist $body $ns]
   }

An example of its use:

   set q [lambda {x} {incr x}]
   {*}$q 1
   % 2

The significant thing here is that (in the above example) $q will contain an anonymous proc which will byte compile itself. So subsequent invocations of {*}$q will not incur a recompilation. The anonymous proc will persist as long as it's not shimmered away, and can be passed around as a value!

This is ubercool - guilt-free lambda.

NEM notes also that in many places where lambdas are useful, the explicit {*} is not necessary -- e.g. most commands which accept callbacks will automatically expand the command anyway:

 % lsort -command [lambda {x y} {
     expr {[string length $x] < [string length $y]}
   }] "My name is Neil"
 name Neil My is
 % trace add variable ::foo write [lambda args {
     puts "foo = $::foo"
 }]
 % set foo 12
 foo = 12
 12

pmarin. Scheme like define:

 proc def { _name arglist body {ns {}} } { 
    upvar $_name name        
    set name [list ::apply [list $arglist $body $ns]]
 }
   
 def q {x} {incr x}
 >{*}$q 1
 2

With this unknown function is possible to call an anonymous proc like a normal proc (without "{*}$" )

 rename unknown _original_unknown
 proc unknown args {
    set _name [lindex $args 0]        
    upvar $_name name
    if { ![catch {set name }]} {
       if { [lindex $name 0] == "::apply"} {
          return [uplevel 1 [list {*}$name {*}[lrange $args 1 end]]]
       } 
    }
    uplevel 1 [list _original_unknown {*}$args]
 }
 
 >def q {x} {incr x}
 ::apply {x {incr x} {}}
 >q 1
 2

Duoas 2009-12-30 09:22

I think it worth noting that abusing the unknown proc with lambdas is just a way to walk circles around Tcl's proc command, and, IMHO, negates the guiltlessness of lambda. If you are going to give a name to a proc, why not do it the Tcl way? The usefulness of lambda is nicely illustrated by NEM above -- where he applies a truly nameless proc to his commands. Once the proc is named, there is no point to a lambda.

 % proc q {x y} {
    return [expr {[string length $x] < [string length $y]}]
 }
 % lsort -command q [list My name is Michael]
 Michael name My is

If all you want is to keep a proc name out of the global namespace, then use a private namespace for your proc names.

My $0.02.

pmarin 2009-12-30 The Unknown proc is just another tool in my toolbox, you are free to use it or not :) You can specific the namespace for the unknown command if you like. You can also to name a lambda function using a interp alias:

interp alias {} q {} {*}[lambda {x} {incr x} ] }

I have written the function becouse when I am prototyping with Tcl I find the language too verbose (to type "{*}$" is not very comfortable in a spanish keyboard) so I have a lot of shorthands in my toolbox like car, cdr, system, dir, sleep, date and so on that make the language less verbose and fun, later many of them are removed from the code.

Hacking the syntax is one of the cool things of Tcl, without it is like to use C without pointers.

NEM See also namespace unknown and Locally-scoped command aliases are fun! for making Tcl even more Scheme-like.