proc rpn {body args} { foreach word $body { switch -- $word { drop {pop args} dup {push args [lindex $args end]} swap {push args [pop args] [pop args]} + - "-" - * - / - % { #-- binary arithmetic operators: set 1 [pop args] push args [expr [pop args] $word $1] } default {push args [$word [pop args]]} } } set args } # Simple stack routines: interp alias {} push {} lappend proc pop stackName { upvar 1 $stackName stack K [lindex $stack end] [set stack [lrange $stack 0 end-1]] } # ..and the indispensable [K] combinator: proc K {a b} {set a}This test will display the source file on stdout. Notice how no variables are needed at all (if you don't count the stack as the Big Variable :
puts [rpn {open dup read swap close drop} rpn.tcl]What happens is the same as with
proc readfile fn { set fp [open $fn] set res [read $fp] close $fp return $res }but the code feels quite different ;-) Schematic of how it works:
(initial stack:) rpn.tcl open filexxx dup filexxx filexxx read filexxx (text) swap (text) filexxx close (text) "" drop (text)and the final stack, which in one element contains the file's contents, is returned to the caller.# Testing the newly added arithmetics, which cost the 4 LOC above:
puts [rpn {+ *} 4 2 1] ;# (2+1)*4 -> 12
Wow, Richard, what a delightful wizzlet! -jcw
A less minimal, but much more capable version is at RPN again.