Incomplete Recursion

The Dodekalogue which defines Tcl is completely recursive, in that command substitution is performed over words (7. Command Substitution) and over the completely-substituted command (2. Evaluation).

It is useful to consider incompletely recursive Tcl, where the invariant in (2. Evaluation, 'These substitutions are performed in the same way for all commands') was abrogated.

One reason to consider this is that the universality of application seems to be surplus to requirements... it seems that it restates in (2.) what is already strongly implied by (7.) through (2.) As post-Euclidean Tcl suggests, there may be virtue in reconsidering this kind of duplication and over-constraint.

It is worth noting that Tcl (as defined by the Dodekalogue) is only defined with respect to command substitution where those commands are reachable from the namespace. The unknown functionality is not specified by the Dodekalogue, which is silent on what occurs if a command name does not resolve to a command. As unknown is given the fully-substituted list which was to be evaluated, it is freely able to re-interpret the list however it chooses. This permits some non-Tcl languages to be implemented over Tcl.

Another reason abrogating the universal-application sub-rule makes sense is that it permits one to do interesting things within Tcl's incompletely recursive definition, which supports the simulation of almost-Tcl within Tcl.

Consider one example of such a useful almost-Tcl language, modeled on .ini file format:

section {
    var value
    var1 value1; var2 value2
}

section2 {
    # this defines section2
    var value; var1 [expr {$var * 2 + $section::var1}]
}

As a means of initializing a dict, or series of namespaces where one is only interested in assigning values to 'variable' names within sections within that structure.

Currently, Tcl does not directly support this kind of language using unknown, as it is impossible to distinguish between a substitution under Dodekalogue (2. STEP 1) word substition and (2. STEP 2) command substitution, and thus impossible to apply different command semantics according to the command's role.

A more fully-worked example of a potentially useful Tcl-like language may be found here: Configuration Language using Unknown


aspect .. although my original misgivings have been allayed, I'm still uncomfortable with this idea and I think I know why:

Your example:

section {
    e  2.78
    pi 3.14
    i [expr {sqrt(-1)}]
    one [expr {-e**(pi*i)}]
}

the part invoking expr is invoking a completely different language from that in the argument to section. Making them both look like Tcl is misleading. How I see what you want is to pass an argument to "commands" in section that can be Tcl code -- in a similar way to what we can already do with foreach, proc etc.

The natural way to approach this would be to delimit the arguments that evaluate in a special way:

section {
    e  2.78
    pi 3.14
    i {[expr {sqrt(-1)}]}
    one {[expr {-e**(pi*i)}]}
}

I suppose it would be nice if you could do something a little more pretty such as:

section {
    e  2.78
    pi 3.14
    apples "tasty little devils"
    i {expr {sqrt(-1)}}
    one {expr {-e**(pi*i)}}
}

.. this makes me wonder if it is possible to hook "" substitution in such a way that might make this possible? Can we do something like replace subst?


asnarb - 2010-06-04 12:47:43

I dunno. This sounds awfully postmodern to me.

That's a good approach for natural languages -- the meaning of every word and phrase is contextually dependent on all the words and phrases surrounding it (and in many cases so is the *parse tree* for each phrase) -- but I think not such a great approach for programming languages.

AMG: Tcl has been keyword-less since it was first created in 1988. The Tcl interpreter turns each line of your script into a list of "words". It neither knows nor cares about the semantic meaning of the words, except for the first word of each line which it takes to be a command name. Each command decides what the words mean. The only way to know whether any given word is a variable name, a number, a text label, a format code, a noise word, a dummy word, etc., is to run the program. (Usually you run the program in your head, simply by looking at the first word of the line and checking the manual for the command of that name.) Basically, every command establishes its own little language. Furthermore, everything is a string, so you can't tell whether "2" is a number or a text label, but you don't care since the distinction doesn't matter anyway.