2010-07-13 25 views
7

A Pregunta puramente teórica sobre Tcl.Tcl Funciones anónimas

Siguiendo this question Estaba pensando en cuál sería la mejor manera de implementar funciones anónimas en Tcl.

El resultado final debe permitir que un desarrollador para pasar un proc completo como un argumento para anohter proc:

do_something $data {proc {} {input} { 
    puts $input; 
}}; 

que sería similar a la de JavaScript

do_something(data, function (input) { 
    alert(input); 
}); 

ahora, naturalmente, esto no lo hará trabaja OOTB. Estaba pensando en algo de este tipo:

proc do_something {data anon_function} { 
    anon_run $anon_function $data 
} 
proc anon_run {proc args} { 
    set rand proc_[clock clicks]; 
    set script [lreplace $proc 1 1 $rand]; 
    uplevel 1 $script; 
    uplevel 1 [concat $rand $args]; 
    uplevel 1 rename $rand {}; //delete the created proc 
} 

Esto funciona. Pero esperaba obtener sugerencias para un mejor patrón luego de esto, ya que no es muy elegante y no usa realmente buenas funciones de Tcl. Sobre todo me gustaría deshacerme de llamar manualmente al anon_run.

Respuesta

11

En Tcl 8.5, puede usar el comando apply. (! recomendada)

proc do_something {data anon_function} { 
    apply $anon_function $data 
} 
do_something $data {{input} { 
    puts $input 
}} 

Por supuesto, si usted está estructurando sus devoluciones de llamada como prefijos de comando entonces se puede hacer esto:

proc lambda {arguments body} { 
    # We'll do this properly and include the optional namespace 
    set ns [uplevel 1 namespace current] 
    return [list ::apply [list $arguments $body $ns]] 
} 

proc do_something {data command} { 
    {*}$command $data 
} 

do_something $data [lambda {input} { 
    puts $input 
}] 

Si está utilizando 8.4 o antes, se necesita el code from the Tcler's Wiki como sustituto, pero tenga en cuenta que esas soluciones solo son semánticamente equivalentes (en el mejor de los casos); no son equivalentes al rendimiento.

+0

También tenga en cuenta que, a diferencia de Javascript, no tiene cierres. Los cierres son semánticamente complicados en Tcl porque realmente no encajan con el modelo de tipo de datos de TLC, y los términos lambda como los anteriores hacen que este problema sea particularmente obvio (no es un gran problema con los procedimientos, simplemente es una cuestión simple de programación). –

+0

Agradezco la respuesta detallada y bien explicada. –

+0

Y he pirateado una [forma limitada de cierres] (https://chiselapp.com/user/kbk/repository/tclquadcode/artifact/9cd98bc023dd3ef1?ln=353,382) para uno de mis proyectos. –

Cuestiones relacionadas