Version 20 of pure list

Updated 2010-03-27 18:47:08 by AMG

A pure list in Tcl is a value that has a list internal representation but no string representation.

Pure lists are significant primarily because the evaluator and bytecode compiler treat them specially. If confronted with a pure list, these components can recognize immediately that

  • the object in question is a single Tcl command; the words making up the command are precisely the elements of the list.
  • the object requires no substitution.

They can therefore avoid using a parser on the object. They simply look up the command (element 0 of the list), and construct a parameter vector consisting of the list elements.

Pure lists are preferred for callbacks such as traces, [eval] and [uplevel], [after] calls, Tk commands and bindings, and similar applications.

The [list] command always returns a pure list. Lars H: Actually, this isn't completely true. See [L1 ].

AMG: Why is empty string not considered to be a zero-length pure list?


Is it essential that there be no string rep - isn't a list rep sufficient for this either way? -jcw

DGP: Yes, it is essential that there be no string rep. Consider these two strings:

 list a set a 1 set b 2

 list a
 set a 1
 set b 2

Both of those strings are valid Tcl lists. In fact they are both the same list. However, they are not the same string, and when evaluated as scripts, they are not the same script.

This distinction is important because [eval] sees newlines as the ends of commands, while [list] sees them as just another whitespace character to separate list elements.

Aha! So this means that one cannot construct a string, do an llength to force a list rep, and then expect the result to eval quickly. That's unfortunate. Is there a simple way to *force* a string to a pure list rep in Tcl?

DGP: [lrange $string 0 end] appears to work, but I don't know that I would count on it. I could easily someone optimizing that "no-op" away.

Another thought: would it be possible to further special-case eval, so that it still uses the list rep if the string has no newlines? OTOH, perhaps it's not worth the extra scan.

DGP: Haven't thought about it, but one would need to check for semi-colons too, at least.

KBK: It's a good bit messier than that. Consider one simple example:

 % set foo bar
 bar
 % set grill {list $foo}
 list $foo
 % lrange $grill 0 end
 list {$foo}
 % eval $grill
 bar

You'd have to make sure that the string is free of substitutions, which would almost defeat the purpose.


An interesting example for list conversion was shown by DKF in the Tcl chatroom on 2002-12-10:

 % set t a\ b\ c\\\ d\ e ;# legal string markup (blanks escaped)
 a b c\ d e              ;# The backslash is still there
 % lrange $t 0 end       ;# Is this a valid list?
 a b {c d} e             ;# Yes, though it looks different
 % set t                 ;# ..and the string rep still has the backspace
 a b c\ d e
 % set t [lrange $t 0 end] ;# Now reassign the pure list to t (= throw away string rep)
 a b {c d} e
 % set t                 ;# The new string rep is re-created from the list
 a b {c d} e