Dinesh
Dinesh

Reputation: 16438

Using argument expansion {*} with more than one statement

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

Answers (1)

Peter Lewerin
Peter Lewerin

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

Related Questions