Version 65 of Quoting hell

Updated 2013-12-13 06:45:33 by AMG

Summary

Quoting Hell is where you are when you've backed yourself into a corner, and now find yourself desperately escaping escape characters in your programming language, clinging to the hope that if you add another backslash or two, "it might work". In some languages, this is the natural state of things. In Tcl, it happens when you're on the newbie learning curve and haven't yet come to the a-ha! moment about the code/data duality of Tcl values. You know you're in quoting hell when your Tcl code begins to look like Perl. Thankfully, unlike some other languages, quoting hell can be mostly avoided in Tcl. To learn how, digest the contents of Tcl Quoting!

Examples

Bad (from the [Macports file macports.tcl):

eval curl fetch $verboseflag {$source} {$tarpath}

Fixed:

eval [list curl fetch $verboseflag $source $tarpath]

APN The above two lines are not equivalent if $verboseflag is not a single "word". If it is known to be a single word, it is not clear to me why an eval is needed at all.

AMG: My assumption is that $verboseflag is either "-verbose" or empty string. So yes, in that case the two are not equivalent. Instead try:

eval curl fetch $verboseflag [list $source $tarpath]

Or even better, use {*}:

curl fetch {*}$verboseflag $source $tarpath

I find that {*} obsoletes [eval] in almost every practical case.


Bad (from the [Macports file macports.tcl):

$workername eval set $opt \{[set $opt]\}

Fixed:

$workername eval [list set $opt [set $opt]]

Bad (from the [Macports file macports.tcl):

$workername eval set system_options($opt) \{[set $opt]\}

Fixed:

$workername eval [list set system_options($opt) $opt]

Bad (from the MacPorts file macports.tcl):

$workername eval "proc PortSystem \{version\} \{ \n\
    package require port \$version \}"

Fixed:

set script {                                                                                                      
    proc PortSystem {version} {                                                                                   
        package require port ${version}                                                                           
    }                                                                                                             
}                                                                                                                 
set script [string map  [list \${version} [list $version]] $script]                                               
$workername eval $script