proc 0 {then else} {uplevel 1 $else} proc 1 {then else} {uplevel 1 $then} ;# the famous K combinatorGlory be to the 11 rules of man Tcl that this is already a crude though sufficient reimplementation:
set x 42 [expr {$x<100}] {puts Yes} {puts No}The bracketed expr command is evaluated first, returning 0 or 1 as result of the comparison. This result (0 or 1) is substituted for the first word of this command. The other words (arguments) are not substituted because they're curly-braced, so either 0 or 1 is invoked, and does its simple job. (I used uplevel instead of eval to keep all side effects in caller's scope). Formally, what happened to the bracketed call is that it went through "applicative order" evaluation (i.e., do it now), while the braced commands wait for "normal order" evaluation (i.e., do when needed, maybe never - the need is expressed through eval/upvar or similar commands).Though slick at first sight, we actually have to type more. As a second step, we create the If command that wraps the expr invocation:
proc If {cond then else} { [uplevel 1 [list expr !!($cond)]] {uplevel 1 $then} {uplevel 1 $else} } If {$x>40} {puts Indeed} {puts "Not at all"}This again passes impromptu tests, and adds the feature that any non-zero value counts as true and returns 1 - if we neglect the other syntactic options of if, especially the elseif chaining. However, this is no fundamental problem - consider that
if A then B elseif C then D else Ecan be rewritten as
if A then B else {if C then D else E}so the two-way If is about as mighty as the real thing, give or take a few braces and redundant keywords (then, else).Luckily we have an if in Tcl (and it certainly fares better in byte-code compilation), but on leisurely evenings it's not the microseconds that count (for me at least) - it's rather reading on the most surprising (or fundamental) ideas, and demonstrating how easily our good old Tcl can bring them to life...
fut This is in fact how Smalltalk does if, and also how boolean values are expressed in lambda calculus.
Next you should show us how to do everything using just NAND. - RS: Not everything, but all Boolean functions - follow that link ;-)
Well, I say his article on Gödel-number source code is long overdue.DKF - Note that the most trivial way of discovering a Gödel-number for a Tcl script is using the binary command but you are going to run into problems with scripts of any length more than a few bytes:
proc Gödel {script} { binary scan $script c* bytes set result 0 foreach b $bytes { set result [expr {$result*256+$b}] } return $result }Mind you, in general Gödel-numbers are very big anyway. IMO, it's easier to work with strings...See Brute force meets Goedel for Gödel numbers at work :)
FW: I'm probably being overly facetious here, but you can also just use
proc If {cond then else} { set false 1 while $cond {set false 0; uplevel 1 $then; break} while $false {uplevel 1 $else; break} }if while is still available to you. - RS: Sure enough, but the idea was rather to do without any branching control structures - switch could have been used too...
KBK See Combinator engine for how all control structures can be expressed with two functionals:
K a b = a S a b c = a c {b c}With these in your pocket, you don't need named variables, named functions, [if], [while], ... These operations plus simple arithmetic are Turing complete.DKF Technically, you don't need simple arithmetic either. You can construct things that behave just like integers (well, something that obeys Peano Arithmetic Axioms) from S and K on their own using things like Church Numerals (I think that's the right name).KBK Hmmm, I think that I had the Church numerals in the combinator engine page even before I wrote the above; you're perfectly right, of course, that S and K can do arithmetic. Just chalk it up to a "Homer moment." (D'oh!)
What other commands could we get rid of? Tcl in tcl
See also If we had no proc - If we had no variables
Arts and crafts of Tcl-Tk programming