Reputation: 16438
I am using {*}
in tcl for argument expansion and come across this issue.
#!/usr/bin/tclsh
set reset {
set count 0;
set age 24;
}
puts $reset
eval $reset; # This is working fine. Commented out the below line and tried
{*}$reset; # This is throwing error. Commented out the above line and tried.
if { [ info exists count ] && [ info exists age ] } {
puts "count & age initialzed to $count and $age"
} else {
puts "count & age not initialzed :("
}
As you see, I have the reset variable defined and I am evaluating with eval
as well as with {*}
.
While eval
is working fine, {*}
is throwing error as
wrong # args: should be "set varName ?newValue?"
while executing
"{*}$reset"
Then I have changed the variable reset
as follows,
set reset {
set count 0;
}
i.e. I have removed the 2nd set
statement and the code works fine.
Why {*}
is working fine with one statement and not with more than that ? Or What I am missing here ?
Upvotes: 0
Views: 191
Reputation: 13282
Commands lite eval
and uplevel
(and while
and if
etc) can evaluate scripts, i.e. strings/lists that consist of zero or more command invocations. When you invoke {*}$reset
you get six words instead of one, but the interpreter still expects a single command invocation. What actually gets invoked is the command set
with five arguments, and the command will balk at that.
Expanding a word into several words works as long as the expansion forms exactly one command invocation:
set foo bar
# => bar
Too few words:
set cmd set
# => set
{*}$cmd
# => wrong # args: should be "set varName ?newValue?"
Too many words:
set cmd {set foo baz ; set abc def}
# => set foo baz ; set abc def
{*}$cmd
# => wrong # args: should be "set varName ?newValue?"
Just right:
set cmd {set foo}
# => set foo
{*}$cmd
# => bar
set cmd {set foo baz}
# => set foo baz
{*}$cmd
# => baz
Also just right:
set cmd set
# => set
{*}$cmd ghi jkl
# => jkl
set cmd {set mno}
# => set mno
{*}$cmd pqr
# => pqr
Documentation: eval, if, set, {*}, uplevel, while
Upvotes: 2