# Church Numerals with ParentheTcl's Lambda Function # # Let $f be a function and $x be some object. # $0 is a function such that [[$0 $f] $x] == $x (* it applies f 0 times *) # $1 is a function such that [[$1 $f] $x] == [$f $x] (* it applies f 1 times *) # $2 is a function such that [[$2 $f] $x] == [$f [$f $x]] (* it applies f 2 times *) # $3 is a function such that [[$3 $f] $x] == [$f [$f [$f $x]]] etc. # # $succ is a function such that [$succ $0] == $1 # [$succ $1] == $2 # [$succ $2] == $3 etc. # # Function composition is multiplication of Church Numerals -- see proc * below. # # In ParentheTcl, the noise word "call" is added, both after "lambda", and before # the function object to be invoked. It makes Tcl happy with repect to shimmering # Tcl's own command objects, and it allows for strong typing and thus better # performance in ParentheTcl, by indicating what type the arguments are and the # result is going to be. Conventionally, we say "call" when all arguments and # the result are all type (tcl). # # See also: # * http://en.wikipedia.org/wiki/Church_numeral # * http://www.madore.org/~david/programs/unlambda/#howto_num if [llength [info commands p7proc]] { set Compiling true } else { set Compiling false source testing.tcl } if $Compiling { p7proc zero {} { lambda call {f} { lambda call {x} { return $x } } } p7proc one {} { lambda call {f} { lambda call {x} { call $f $x } } } p7proc two {} { lambda call {f} { lambda call {x} { call $f [call $f $x] } } } p7proc succ {} { lambda call {n} { lambda call {f} { lambda call {x} { call $f [ call [call $n $f] $x] } } } } p7proc tick {} { lambda call {s} { return "I$s" } } ;# a function that finally does something! } else { set 0 [zero] set 1 [one] set 2 [two] set SUCC [succ] set TICK [tick] # use SUCC to make more integers set 3 [call $SUCC $2] set 4 [call $SUCC $3] AssertEq "." { call [call $0 $TICK] "." } AssertEq "I." { call [call $1 $TICK] "." } AssertEq "II." { call [call $2 $TICK] "." } AssertEq "III." { call [call $3 $TICK] "." } AssertEq "IIII." { call [call $4 $TICK] "." } } if $Compiling { p7proc compose {} { lambda call {f} { lambda call {g} { lambda call {x} { call $f [ call $g $x ] } } } } } else { # composition is multiplication proc * {a b} { call [ call [compose] $a ] $b } # 3 * 4 = 12 AssertEq "IIIIIIIIIIII." { call [call [ * $3 $4 ] $TICK] "." } Okay }