Version 25 of {expand}

Updated 2004-08-08 22:54:29

With Tcl 8.5, {expand} becomes the closest thing Tcl has to a conventional keyword. See TIP 157 [L1 ] for the details. [expand syntax ...]


NEM OK - here's an attempt at explaining {expand} in Tcl 8.5. The easiest way to explain is perhaps with an example. Consider the following code, which may be used for launching a browser on Windows:

 eval exec [auto_execok start] [list $url]

The reason that the [eval] is there is that [auto_execok] may return a list which represents the command to be run. This list needs to be "flattened" for exec. For instance, let's say [auto_execok start] returned:

 % auto_execok start
 c:/windows/command.com /c start

If you just did:

 exec [auto_execok start] $url

You would get an error about "can't find 'c:/windows/command.com /c start' - no such file or directory" or something similar. In order to flatten this list, Tcl before 8.5 requires use of [eval] (or more arcane uplevel equivalents) which does this for you (as it concats its arguments together before evaluation).

So, why not just say

 eval exec [auto_execok start] $url

Because the $url may contain spaces, so we need to protect it so that it doesn't get flattened. So, for pre Tcl 8.5 programmers, the safe way to code is via the use of [list]:

 eval exec [auto_execok start] [list $url]

There are lots of gotchas with quoting arguments correctly for [eval]. So, to solve this problem, 8.5 introduced the {expand} syntax, which inline expands arguments in a command invocation. What this means is that {expand}list becomes word word word... at invocation time. So, we can now rewrite our example (in 8.5) as:

 exec {expand}[auto_execok start] $url

which is clearer, safer (by avoiding eval) and better all round.


RS: {expand} is, so to speak, the inverse of list. It is not a command (because every command returns one single word), but an extension to the Tcl syntax. Consider:

 {expand}[list 1 2 3]

produces the three words

 1 2 3

And for using expand, it is good to look out for places where eval is used:

 eval pack [winfo children .]

is equivalent to

 pack {expand}[winfo children .]

But for code to be given to others (which might still run 8.4, 8.3 or older), best avoid {expand} for a while...


LES: Would someone remind us again why this command had to be braced? Why {expand} instead of expand? Why not [ expand [ list 1 2 3 ] ] ?

MG - I think it's because expand isn't actually a command, like [list], or [pack], etc; it's more of an 'option'. If you used [expand [list 1 2 3]]] you'd get an 'invalid command name' error. It's a little confusing, I think, since it seems to be different to all other aspects of the Tcl syntax. . .

SLB: The syntax was controversial. One discussion of the subject is recorded in DISCUSSION: Argument Expansion Syntax. See especially the comments from MS towards the end.

Because backward compatibility (a virtue to be sure) overrode aesthetics (a higher virtue, IMO).

Hmmmmm. Those who find

    ... [expand [list 1 2 3]] ...

superior aesthetically should, CL believes, re-read the discussion and Miguel's comments. {expand}'s introduction is not some sort of reactionary defense of abstract compatibility principles; instead, it preserves valuable syntactic simplicity.

I agree that the functionality warranted new syntax. It's just that the chosen syntax is exceptionally ugly, and it seemed that pretty much everyone agreed that it was ugly, but it was backwards compatible. But since I've engaged in this argument before and lost, there's no point in having it again. It's also the reason why I'm not putting my name on this.

Although, given that Tcl's big claim to fame is having almost no syntax (Tcl: Just 11 syntax rules!), I'm still curious as to how a 12th syntatctic rule (Tcl: Now with almost 10% more syntax!) makes it into a minor revision.


Category Tutorial | Dodekalogue