tags:

views:

450

answers:

2

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?

+4  A: 

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
RHSeeger
... though I personally find \$option1 \$option2 more preferable to [list $option1] [list $optio2]. It more closely shows intent -- your intent isn't to create one-element lists, your intent is to prevent (or protect against) an extra round of substitution for those variables.
Bryan Oakley
The canonical way to do this for 8.4 and below is: `eval [linsert $mylist 0 myprocedure options1 option2]`
glenn jackman
I don't agree that's canonical (but maybe we have different canons?). It's arguably safest but it's less readable than \$option1 \$option2 and again somewhat obscures what you're actually trying to accomplish.
Bryan Oakley
It should be noted that the expansion syntax of 8.5 (and later) is *strongly* preferred as even seasoned experts used to get into trouble with doing things safely before that. It's also potentially faster.
Donal Fellows
A: 

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"
}
glenn jackman
I disagree that you'd necessarily code myprocedure to take a variable number of arguments (ie, use "args"). Whether you do so depends entirely on whether or not you need it to take a variable number of inputs, not on how one particular caller happens to have it's inputs available to it.
RHSeeger