Fenix713
Fenix713

Reputation: 33

TCL - List with Variables

I am having trouble creating a list of lists that contains a mixture of text and variables in TCL. I have a user input variable that I then want to plug into a list. I will skip the user select option for brevity.

set a 0.1
set b 20.0

set c {
    {text1 text2 $a text3}
    {text4 text5 $b text6}
}

foreach i $c {
    set CheckVal [lindex $i 2]
    puts "Threshold is $CheckVal"
}

Resultant output:
Threshold is $a
Threshold is $b

Desired output:
Threshold is 0.1
Threshold is 20.0

Upvotes: 3

Views: 8339

Answers (2)

Schelte Bron
Schelte Bron

Reputation: 4813

While the methods suggested by Peter Lewerin work, they should only be used as a last resort. Normally you would use some of the commands that operate on lists to create your list of lists. I believe that is what glenn jackman was alluding to.

Depending on your actual code, I would probably use list and/or lappend:

set c {}
lappend c \
  [list text1 text2 $a text3] \
  [list text4 text5 $b text6]

Then the foreach will work as you wrote it.

Upvotes: 2

Peter Lewerin
Peter Lewerin

Reputation: 13252

Two alternatives are

set a 0.1
set b 20.0

set c {
    {text1 text2 a text3}
    {text4 text5 b text6}
}

foreach i $c {
    set CheckVal [lindex $i 2]
    puts "Threshold is [set $CheckVal]"
}

Store the variable name instead of the value, and get the value by a two-step substitution ($$Checkval doesn't work, but [set $CheckVal] does) in the puts invocation.

set a 0.1
set b 20.0

set c {
    {text1 text2 $a text3}
    {text4 text5 $b text6}
}

foreach i $c {
    set CheckVal [lindex $i 2]
    puts [subst "Threshold is $CheckVal"]
}

This is double substitution rather than two-step substitution. It looks simple, but subst is actually a bit tricky and is almost a last-resort technique.

Regardless of which solution you use, this kind of scheme where you store a reference to a variable value in a structure is fragile since it depends on the original variable being in scope and still existing when the reference is dereferenced. At the very least, you should store a qualified name (namespace and name) in your list. If the variable is a local variable, you need to use it during the same call as when it was stored (or from further up the call stack using upvar, but don't go there).

Upvotes: 1

Related Questions