In '''Playing [newLISP]''', Tcl takes on some of the features of that language. One unique feature of newLISP is that the definition of a function can be modified ''during the evaluation of the function''. `stepeval` implements this behaviour, with the small twist that it discards the commands of the script as it evaluates them. This shifts some of the management overhead into `stepeval`, allowing the Tcl examples below to be more concise than their newLISP counterparts. ====== #requires cmdSplit from wiki.tcl.tk/cmdSplit proc evaluator {procns name} { upvar $name lines set lines [cmdSplit [info body ${procns}::$name]] while {[llength $lines]} { set cmd [lindex $lines 0] uplevel 1 $cmd set lines [lreplace $lines[set lines {}] 0 0] } } proc stepeval {proc args} { set fullname [uplevel [list namespace which $proc]] set procns [namespace qualifiers $fullname] set procname [namespace tail $proc] set argspec {} foreach arg [info args $fullname] { if {[info default $fullname $arg val] == 1} { lappend arg $val } lappend argspec $arg } tailcall apply [linsert $args 0 [namespace current]::evaluator \ $procns $procname $procns] } ====== Here is the Tcl version of the [http://kazimirmajorinc.com/Documents/Crawler-tractor/index.html%|%crawler tractor] (see also [http://kazimirmajorinc.blogspot.com/2009/04/crawler-tractor.html]): ====== proc tractor {} { eval { puts [incr counter] lappend tractor [lindex $tractor end] #not needed because $tractor is automatically "consumed" by the evaluator #if {[llength $tractor] > 3} { # set tractor [lreplace $tractor[set tractor {}] 0 0] #} } } ====== To execute `tractor` newLISP-style: ====== stepeval tractor ====== Here is a Tcl implementation of the self-modifying newLISP "factorial" function from [http://pastebin.com/HdQ8hiyx]: ====== proc factorial int { if {$int > 1} { set factorial [linsert $factorial end-1 [lindex $factorial 0]] set factorial [lreplace $factorial end end [list return [expr { $int * [lindex $factorial end end]}]]] incr int -1 } return 1 } stepeval factorial 5 ;# -> 120 ====== <> lisp