Backquoting

See Also

backquote
implementation in Tcl
GenTemplate

Discussion

Richard Suchenwirth 2001-11-29: JCW: PYK 2013-03-03:

Comparing Tcl and LISP:

  • In LISP, normally all atoms are evaluated, variables to their value; so FOO in LISP would amount to $foo in Tcl
  • In LISP, lists or atoms may be quoted( (QUOTE FOO) or 'FOO) to prevent the evaluation; in Tcl, this is curlies around a list, and no special markup for whitespace-less words
  • In a LISP quoted list, it is possible to still evaluate some elements:
'(NOT THIS BUT ,THAT)

where the leading comma ("backquote") triggers the evaluation of THAT, while leaving the other elements quoted.

To expand items in Tcl lists, use [[string map] (available in 8.3.3 and up?):

set template {
    puts $signs
    puts [brackets]
    puts @that@
}

set template [string map [list @that@ [list "simulated backquote"]] $template

Another alternative would be to use [[regsub]:

regsub -all @that@ $template [list "simulated backquote"] template

The @-signs are not Tcl syntax, we picked them ourselves, and surrounding the backquotable element on both sides is more robust if either one bq name is prefix to another (e.g. @dir@ and @dirlist@), or @ signs occur in the text that are not supposed to be substituted.

This technique is useful in generating code, where long text blocks with Tcl-parser-relevant characters shall be left untouched, while parts must still be substituted. For usage examples, see for instance Gadgets or Pipe Servers in C from Tcl.

Notice that the substituted value is first added to a list to make sure that additional words aren't introduced into text which is going to be consumed by a Tcl interpreter.

Using the [[string map] variant, the following is possible:

proc foo {bar} [string map [list #A# $a #B# $b] {
    if {#A#} { puts Yeay! } else { #B# }
}]

Same can be done with format, but given the way its args are ordered, string map seems more readable


Some of these approaches are looking a bit fragile. Be sure you don't overlook the power of a simple subst.

RS: Of course one could embed $variable references in the template. Every other instance of $ (maybe you're generating a shell script, or makefile) then has to be escaped with backslash to be hidden from subst -nobackslashes -nocommands. But I started this page to discuss whether Tcl has an equivalent to Lisp's backquoting, more as a proof of principle...