Passing list to Tcl procedure

2020-06-08 13:32发布

问题:

What is the canonical way to pass a list to a Tcl procedure?

I'd really like it if I could get it so that a list is automatically expanded into a variable number of arguments.

So that something like:

set a {b c}
myprocedure option1 option2 $a

and

myprocedure option1 option2 b c

are equivalent.

I am sure I saw this before, but I can't find it anywhere online. Any help (and code) to make both cases equivalent would be appreciated.

Is this considered a standard Tcl convention. Or am I even barking up the wrong tree?

回答1:

It depends on the version of Tcl you're using, but: For 8.5:

set mylist {a b c}
myprocedure option1 option2 {*}$mylist

For 8.4 and below:

set mylist {a b c}
eval myprocedure option1 option2 $mylist
# or, if option1 and 2 are variables
eval myprocedure [list $option1] [list $option2] $mylist
# or, as Bryan prefers
eval myprocedure \$option1 \$option2 $mylist


回答2:

To expand on RHSeeger's answer, you would code myprocedure with the special args argument like this:

proc myprocedure {opt1 opt2 args} {
    puts "opt1=$opt1"
    puts "opt2=$opt2"
    puts "args=[list $args]" ;# just use [list] for output formatting
    puts "args has [llength $args] elements"
}


回答3:

It might be useful to note that passing your command to catch will also solve this problem:

set a {b c}
if [catch "myprocedure option1 option2 $a"] {
    # handle errors
}

This should probably only be used if you want to handle errors in myprocedure at this point in your code so that you don't have to worry about rethrowing any errors that get caught.