Version 12 of K

Updated 2004-01-13 12:06:17

Short for the K combinator, together with S the fundamental functional operators from which all function composition can be done. It is extremely simple:

 proc K {x y} {set x}

It just returns its first argument (and discards the second). The advantage is that in this way you can hold an intermediate result which you finally want to return, after doing more processing (which ends up in y) where only the side effects matter. Consider popping a global stack (top at end):

 proc pop1 {} {
    set top [lindex $::Stack end]
    set ::Stack [lrange $::Stack 0 end-1]
    return $top
 }

or, implemented with K:

 proc pop2 {} {K [lindex $::Stack end] [set ::Stack [lrange $::Stack 0 end-1]]}

One command less, one variable less, a slick one-liner (from: A different FORTH).

See Hot curry and Combinator engine for more details than you'd expect ;-)


Another use of K is for making a get-and-unset command, which can be rather useful for efficient handling of Tcl_Objs. Note that this is not done as a procedure (AJD but surely K is a procedure?); that adds quite a bit of execution overhead.

Replace $someVar with:c

 [K $someVar [unset someVar]]

AJD Note, that if someVar is going to be reused, then it is more efficient to:

 set someVar [someFunc [K $someVar [set someVar ""]]]

...as this avoids deleting then recreating the somevar variable. Of course this assumes that someFunc is able to make more efficient use of a singly referenced Tcl_Obj - the common examples are lrange and linsert.


K provides profound performance advantages that are not immediately apparent, changing common operations from quadratic in data length to constant scale. Helmut Giese writes about this in [L1 ] and [L2 ]. It also shows up in many performance discussions, such as how to shuffle a list.


A generalized K, that returns the first of its arguments:

 proc K {arg args} {set arg}

can also be used as identity operator with one argument, which comes in handy when using if like this (remember it returns the result of the applying branch):

 set result [if $condition {K yes} else {K no}]

which is another way for writing

 set result [expr {$condition? "yes" : "no"}] ;# RS

DKF: However, this is not really K as that is a two-argument combinator; indeed, there's no such thing as an n-arg combinator as every one has to have a specific number of arguments (which is enforced by the binding and evaluation rules of combinator theory - need reference on Head Normal Form here, but none handy.) It makes more sense though for Tcl though, which (normally) knows how many arguments there are without looking at the command name.


Lambda in Tcl can also be had as a one-liner with K:

 proc lambda {argl body} {K [set n [info level 0]] [proc $n $argl $body]}

In the Tcl chatroom, Miguel pointed out "inline K":

 [K a b] ~ [lindex [list a b] 0]

That's slightly faster in 8.4+, as it is all bcc'ed.


Category Concept | Arts and crafts of Tcl-Tk programming