Reputation: 461
I am trying to substitute a variable in a list:
% set a 1
1
% set b {1 $a}
1 $a
%
% set a 1
1
% set b [list 1 $a]
1 1
When I use the curly braces {}
, to define the list the variable 'a' doesn't get substituted with its value but in case of using list
it does.
How do I substitute a variable's value when using a list defined with {}
?
Upvotes: 3
Views: 7016
Reputation: 137567
How do I substitute a variable's value when using a list defined with {}?
In short, you don't.
What {}
really does is define an unsubstituted string. It might be possible to interpret that as a list, but it could be other things as well, such as script. It's part of the fundamental nature of Tcl that it is all of these things.
If you want the variable substituted, you use a different sort of quoting or you run the result through subst
(which is defined to work over strings). The “quoting” most commonly used for lists these days is the list
command, as that preserves element boundaries correctly.
I suppose it is possible to do things with various string operations to make a command that could post-process the string as you want, but it would be slow and complicated:
proc substList {string} {
# Add backslashes in front of metacharacters
set safer [string map {\\ \\\\ [ \\[ ] \\]} $string]
# Convert variable mentions to our “safe” version
regsub -all {\$\w+} $safer {[list &]} tmpl
# Do the substitutions in the caller's context
tailcall subst $tmpl
}
Giving a quick test:
% set a "1 2 3"
1 2 3
% set b {x $a}
x $a
% substList $b
x {1 2 3}
Appears to work in this simple case, though I wouldn't want to warrant that it's actually right. (After all, it's using string map
and regexp
and subst
; what could possibly go wrong?) Just use list
properly, OK?
Upvotes: 1
Reputation: 13252
% set a 1
1
% subst {1 $a}
1 1
% set b [subst {1 $a}]
1 1
But most Tcl:ers actually prefer to use list
when creating a list value with substitutions, like in your second try:
% set b [list 1 $a]
One reason for this is that subst
won't preserve list structure in the value:
% set a {a b}
a b
% set b [subst {1 $a}]
1 a b
% set b [list 1 $a]
1 {a b}
Another possibility is to use double quotes instead of braces; this also won't preserve list structure.
% set b "1 $a"
1 a b
Documentation: list, set, subst, Summary of Tcl language syntax
Upvotes: 5