Arising from a discussion (on [Tcl chatroom] about the [denotational semantics] of Tcl, the concept of ''tcl-null'' was proposed.
[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 [namespace]s 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 [Lappend]ing 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
* [If we had no if]
* [If we had no variables] (who needs [set] when we have [proc]?)
* [Combinator engine] (build a Turing-complete language without variables, and without named functions, and without a lot of other things.)
----
[[
[Category Concept]
]]