Forum Discussion
Variable substitution in switch statement not working
From the Tcl man page: https://www.tcl.tk/man/tcl8.4/TclCmd/switch.htm:
Two syntaxes are provided for the [switch] pattern and body arguments. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line switch commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the pattern arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behavior of the second form different than the first form in some cases.
This gets into the guts of Tcl. Every statement in Tcl is a command. A command always follows the same pattern, namely:
command ?arg? ?arg? ...
This includes things that are normally built-ins for other languages. Take if, for example. Normally, you'd write it like this:
if { $a eq "foo" } {
; do something...
} else {
; do something else ...
}
It turns out that, in Tcl, the squirly braces ({}) are always non-interpolating quote operators. They specifically are not block delimiters. Non-interpolating quotes take away the special meaning of characters ... including the newline character. So in reality, that entire code block is effectively on one line and looks like this:
if { $a eq "foo" } { ... } else { ... }
So it is a command (if) followed by four arguments. As weird as it may seem to programmers from other languages, else, in this construct, is an argument. (Side note: for iRules, the developers hacked this a bit so that you can do uncuddled if...else blocks, but that's an iRules thing, not a Tcl thing).
So, considering just Tcl, the following:
set x "foo"
switch "foo" { "abc" { puts "abc" } "$x" { puts "x" } default { puts "default" } }
would print "default" because $x is not expanded in this form. However, this:
set x "foo"
switch "foo" "abc" { puts "abc" } $x { puts "x" } default { puts "default" }
would print "x".
There is another form that work, namely:
set x "foo"
switch foo \
"abc" { puts "abc" } \
$x { puts "x" } \
default { puts "default" }
because the backslash takes away the meaning of the newline following it. A newline is normally a statement separator. By taking away the special meaning, this again ends up effectively on one line.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com