2009-10-20 14 views
11

¿Cuál es la manera canónica de pasar una lista a un procedimiento Tcl?Pasando la lista al procedimiento Tcl

Me gustaría mucho si pudiera obtenerlo para que una lista se expanda automáticamente en una cantidad variable de argumentos.

Así que algo como:

set a {b c} 
myprocedure option1 option2 $a 

y

myprocedure option1 option2 b c 

son equivalentes.

Estoy seguro de que vi esto antes, pero no puedo encontrarlo en línea. Cualquier ayuda (y código) para hacer que ambos casos sean equivalentes sería apreciado.

Esto se considera una convención estándar de Tcl. ¿O incluso estoy ladrando el árbol equivocado?

+0

Ca agrega la palabra "unwrap" (mejor que en "desenvolver argumentos") en algún lugar de su gran pregunta? Me costó encontrarlo :-) – cfi

Respuesta

14

Depende de la versión de Tcl que está utilizando, pero: Para 8.5:

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

el 8,4 y abajo:

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 
+1

... aunque personalmente encuentro \ $ option1 \ $ option2 más preferible a [list $ option1] [list $ optio2]. Muestra más de cerca la intención: su intención no es crear listas de un elemento; su intención es evitar (o protegerse) una ronda adicional de sustitución para esas variables. –

+0

La forma canónica de hacer esto para el 8.4 y siguientes es: 'eval [linsert $ mylist 0 myprocedure options1 option2]' –

+2

No estoy de acuerdo con que sea canónico (¿pero quizás tenemos diferentes cánones?). Es posiblemente el más seguro, pero es menos legible que \ $ option1 \ $ option2 y de nuevo oscurece algo que realmente está tratando de lograr. –

0

Para ampliar la respuesta de RHSeeger, sería codificar MyProcedure con el argumento args especial como este:

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" 
} 
+0

No estoy de acuerdo con que necesariamente codifique myprocedure para tomar una cantidad variable de argumentos (es decir, use "args"). Ya sea que lo haga depende completamente de si necesita o no tomar una cantidad variable de entradas, no de cómo una persona que llama en particular tiene sus entradas disponibles para ella. – RHSeeger

0

Podría ser útil tener en cuenta que la aprobación de su mando a catch también va a resolver este problema:

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

Esto se debe probablemente sólo se utiliza si quiere controlar los errores en MyProcedure en este momento de su código para que usted don' Tengo que preocuparme por volver a lanzar cualquier error que pueda atrapar.

Cuestiones relacionadas