I have a code in which I am passing a list to be evaluated, by TCl uplevel #0. While it works well if I give it a code which uses curly braces in order to wrap the square braces, for example:
uplevel #0 { puts [ info vars CCK_* ] }
I cannot get to accept when I use a list, i.e.:
uplevel #0 [list puts "\[" info vars CCK_* "\]" ]
I get:
wrong # args: should be "puts ?-nonewline? ?channelId? string"
while executing
"puts {[} info var CCK_* \]"
("uplevel" body line 1)
invoked from within
"uplevel #0 [ list puts "\[" info var CCK_* "\]" ]"
I need the list command , because some of the rest of the code requires evaluation of variable names, that must happen before uplevel takes order ( i.e., input to uplevel). For example:
if { [ getpoint $elem ] == $pointy }
when [ getpoint $elem ]
is to be evaluated in the uplevel, but pointy actually is defined and set in the calling proc , hence I cannot use curly braces for it, there will be evaluation before uplevel is called, and it would get just a number.
Thanks,
Assembling a script (or command sequence) to be submitted to uplevel etc. is not necessarily best achieved using list
. This is the case for a script with nested evaluations, for instance.
Your question wording is not fully clear to me (so I might have interpreted it incorrectly), but you might want to consider using [subst]
or [string map]
for your purposes?
Watch:
set CCK_1 ""
proc foo {someVarName} {
uplevel "#0" [subst -nocommands {
if {"$someVarName" in [info vars CCK_*]} {
puts "Found $someVarName"
}
}]
}
foo CCK_1; # prints "Found CCK_1"
foo CCK_2
List are better suited for command sequences without excessive evaluation nesting; for complete scripts, better use script templates based on [subst]
or [string map]
. A word of caution: [subst]
and [string map]
don't protect the substitution values and position them in the script in their literal form.
This is not to say that your original snippet could not be made to work:
set CCK_1 ""
# a) non-robust variant
proc bar {pattern} {
uplevel "#0" puts "\[info vars $pattern\]"
# equiv of
uplevel "#0" [concat puts "\[info vars $pattern\]"]
# versus
uplevel "#0" [list puts "\[info vars $pattern\]"]
}
bar CCK_*
set "CCK _1" ""
# b) robust variant
proc bar-robust {pattern} {
uplevel "#0" puts "\[[list info vars $pattern]\]"
# equiv of
uplevel "#0" [concat puts "\[[list info vars $pattern]\]"]
}
bar-robust "CCK _*"
uplevel
assembles the script to be evaluated by [concat]
ing its arguments. Like providing a single [concat]
'ed the argument. You would not use list
here to assemble the entire script, but rather to protect the script components under assembly (see bar-robust
). Protection here means that complex values are maintained in their original meaning during script assembly (e.g., a match pattern incl. whitespace: CCK _*
).