3

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

Fenix713
  • 33
  • 1
  • 3
  • 1
    read http://www.tcl-lang.org/man/tcl8.5/tutorial/Tcl4.html and http://www.tcl-lang.org/man/tcl8.5/tutorial/Tcl14.html -- the examples in those chapters should provide the answer. – glenn jackman Sep 13 '18 at 22:15

2 Answers2

2

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.

Dexygen
  • 12,287
  • 13
  • 80
  • 147
Schelte Bron
  • 4,113
  • 1
  • 7
  • 13
1

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).

Peter Lewerin
  • 13,140
  • 1
  • 24
  • 27