Greg Buchholz
Greg Buchholz

Reputation: 930

Tcl switch statement and -regexp quoting?

There must be an extra level of evaluation when using the Tcl switch command. Here's an example session at the repl to show what I mean:

$ tclsh
% regexp {^\s*foo} " foo"
1
% regexp {^\\s*foo} " foo"
0
% switch -regexp " foo" {^\\s*foo {puts "match"}}
match
% switch -regexp " foo" {{^\s*foo} {puts "match"}}
match

...There needed to be an extra backslash added inside the first "switch" version. This is consistent between 8.5.0 and 8.6.0 on Windows. Can someone point me to the section of the manual where this and similar instances of extra levels of unquoting are described? My first thought was that the curly brackets in the first "switch" version would have protected the backslash, but "switch" itself must be applying an extra level of backslash susbtitution to the patterns. Unless I'm misunderstanding the nuances of something else.

Edit: ...hmmm... Like Johannes Kuhn says below backslash substitution apparently depends on the dynamic context of use, and not the lexical context of creation...

% set t {\s*foo}
\s*foo
% proc test_s x {set x}
% test_s $t
\s*foo
% proc test_l x {lindex $x 0}
% test_l $t
s*foo
% puts $t
^\s*foo

...that seems to be quite the interesting design choice.

Upvotes: 2

Views: 797

Answers (1)

Johannes Kuhn
Johannes Kuhn

Reputation: 15173

The problem you describe here is simple to solve:

The difference between switch and regexp is that switch takes actually a list.
So if we print the first element of the list {^\s*foo {puts "match"}} with

% puts [lindex {^\s*foo {puts "match"}} 0]
^s*foo

it results in something that we don't want.

List constructing is a little bit complex, if you are not sure, use an interactive Tcl shell that constructs one for you with list.

Edit: Indeed, it is an intresting desin choice, but this applies to everything in Tcl. For example expr uses an minilanguage designed for arithmetic expressions. It is up to the command what it shall do with it's arguments. Even language constucts like if, for, while are just commands that treats one of the arguments as expression, and the other arguments as script. This design makes it possible to create new control structures, like sqlite's eval, which takes the SQL statment and a script that it should evaluate for each result.

Upvotes: 2

Related Questions