Version 10 of DISCUSSION: Argument Expansion Syntax

Updated 2003-07-29 07:30:46

Note that

 eval exec $program $args

is not an adequate substitute for

   eval [linsert $args 0 exec $program]

or

  exec $program {}$args

since it breaks when $program contains spaces.

Option 4: leading @: Larry Smith If you favor a leading character then "@" is easy to see and read, much more so than `.

Option 4: $(<whatever you want expanded>): Larry Smith Personally, I prefer marking a particular string or set of strings for an additional parsing/substitution pass using something that is reminicent of the current syntax. $([cmd]) or $([cmd1] [cmd2]) marks things clearly as being expanded. After all, it is the $ that signifies substitution, not the {}.

  • $([cmd]) is already legal syntax within variable substituition and shouldn't be mixed up with expansion.

Jacob Levy July 28, 2003: What the example above tries to achieve seems to be possible without any new syntax, using a procedure called apply, which behaves as follows:

 set l {a b c d e}
 apply list $l $l
 ==> {a b c d e a b c d e}

The definition of apply is that its first argument is a function that is applied to rest of the arguments which are evaluated and their values are collected into a list.

The definition of apply is probably something like:

 proc apply {fn args} {
     set l ""
     foreach a $args {
         set l [lconcat $l $a]
     }
     return [eval $fn $l]
 }

 proc lconcat {pre el} {
     set l $pre
     foreach e $el {lappend l $e}
     return $l
 }

Now there may be more to TIP #144 that is not covered by this; however, at least for the given example, no new syntax is needed for implementing the functionality in Tcl.

DGP For this specific example, [apply] would be enough, yes.

When you extend things to get a command that can solve all of the problems addressed by the proposed syntax, you end up with the [expand] command proposed in TIP 103.

TIP 103 was considered and rejected.

Can we move on now please?

DGP For that matter, [apply] will not even work for the [exec] example above (when $program contains spaces).

Jacob Levy Fixed the $args handling, above. To handle $prog with spaces in it, you'd need to pass [list $prog] to the invocation of apply.

TP I like the apply option best. I would suggest that the apply command could have it's own mini-language (ala format, regexp, etc) using the {} or ` formatting. E.g.

   apply {somecommand {}$expand_this $but_not_this}

DGP The "special command with its own mini-language" approach was TIP 103.


KBK (2003-07-28) I know that I have code that will break with the backquote syntax.


Setok I know I probably bore people already with my ramblings on the caret expansion syntax but I find it pleasing. Note that expr does not allow double-carets (no logical XOR). So:

  file join ^^$FilePath

or

  exec $program ^^$args

The reason I find it nice is because it actually looks like the operation it is doing. It, to me, feels like real syntax instead of a hack.

The other option I suggested a couple of times was the ability for a command to affect its calling command line. This is somewhat akin to upvar and uplevel in how dangerous it can be, but allows macro-style functionality into Tcl. Other benefits are that no new syntax is added -- only a new capability provided to commands and procedures. I do realise it's somewhat complex.


(Continuing from a thread on comp.lang.tcl)

I think that paired backquotes is a good marker for argument expansion. The desired operation is to unlist something, so having a paired operator seems fitting. In sh, a backquoted string is not a grouping mechanism, but an expansion mechanism. In fact, to be completely analogous to shell programming, a backquoted string would mean to evaluate the backqoted string and retokenize the result. Hmm...I like this. Essentially, the backquotes would be markers more like square braces than like a dollar sign.

Fleshing this out, the examples from Tip #144 would become:

   destroy `winfo children .`
   button .b `subst $stdargs` -text $mytext -bd $border
   exec $prog `set opts1` `getMoreopts` $file1 $file2

(Note that there's a couple of ways to get an expanded variable dereferences. Good thing or bad thing?)

I think this would be very understandable for anybody with a shell programming background, and tcl certainly has a lot of shell heritage. And IMO, it's a lot cleaner. Given that tcl is built around the notion of command/argument, continuing that structure seems like a good thing. I mean, the language doesn't even have infix math operators, and I see proposals for extending the {} syntax with indexes, ranges, etc. That's so far removed from my conception of "the Tcl Way" that it's hard to fathom. After all, wasn't even the dollar sign variable dereference syntax controversial back in the day? "Why do you need a special syntax, you should just use the set command!"

Scott Gargash