Arising from a discussion (on Tcl chatroom about the denotational semantics of Tcl, the concept of tcl-null was proposed.

[ LV 2007 Jan 08 Is this different than the discussion on the null wiki page?]

MS offers this pragmatic approximation of tcl-null:

   set cmds [info command]
   rename catch _catch
   rename rename _rename
   foreach c $cmds {_catch {_rename $c {}}}
   _rename _catch {} 
   _rename _rename {}

but notes that namespaces also have to be cleaned up. - RS: You can have that, and all of the above: a brain-dead interpreter that understands no command any more, with

 namespace delete ::

tcl-null Game

Starting with this as a base, the game is to come up with minimal subset of built-in commands which provide a useful (if not exactly usable) language from which many of the facilities of tcl can be built.

CMcC Sat 23rd Sep 2006. One such set is apply set uplevel list lindex return. This resembles the minimal set of lisp functions necessary to construct classic lisp: (eval) (cond) (lambda) (quote) (car) and (cdr) from which McCarthy could construct/emulate classic-lisp. - RS: list is not needed in the set of fundamentals - the Tcl parser itself builds a list of the arguments before calling a command, so

 proc list args {return $args}

The above set constructs if as:

   proc if {c t f} {uplevel [lindex [list $t $f] [uplevel expr $cond]]}

The construction of proc or a near approximation is left as an exercise for the reader. :) MS says it can be done. I have no idea how. - RS Allowing for an extra interp command, proc is a special case of apply:

 proc f x {expr {$x*$x}}

is equivalent to

 interp alias {} f {} apply {x {expr {$x*$x}}}

dgp pointed out the need for return and also adds if your aim is to get back to the full Tcl built-in set, you'll need trace

This raises the question of the aim of the tcl-null game. I think there are three possible games:

  1. to construct a useful set
  2. to construct a usable set
  3. to construct the full Tcl built-in set.

RS 2006-09-23: If we did not base all looping on recursion (which has its limits), one loop construct would be needed in the fundamental set. while can cover the functionality of for and foreach as well:

 foreach el $list {puts $el}

can be rewritten as

 set i 0
 while {$i<[llength $list]} {
     puts [lindex $list $i]
     incr i

Some more experiments:

 lappend list $el

can be done, for the single element case, as

 set list "$list {$el}"

Cast into a proc, that's (slightly buggy, with a leading " " when Lappending to {}):

 proc Lappend {_list args} {
    set it [uplevel 1 set $_list]
    uplevel 1 "set $_list {$it $args}"

lindex is not fundamental. Here is a replacement which uses a recursive helper function (which in turn uses uplevel 0, the replacement for eval, as I don't have {*} here):

 proc Lindex {list index} {
   uplevel 0 nth $index $list
 proc nth {n {head {}} args} {
   if {$n==0} {return $head}
   if {$n>0} {uplevel 0 nth [expr {$n-1}] $args}

BTW, classic lindex (with only a single index) is redundant in Tcl itself:

 lindex $list $index

could always be written as a simple special case of lrange:

 lrange $list $index $index

Lars H: Not quite, RS -- you also have to remove a level of list-quoting. It's more like

  uplevel 0 {set ""} [lrange $list $index $index]

See also

[ Category Concept ]