2010-07-13 172 views
7

关于Tcl的纯理论问题。Tcl匿名函数

正在关注this question我在想什么是在Tcl中实现匿名函数的最佳方式。

最终的结果应该被允许开发人员通过一个完整的PROC作为参数传递给anohter PROC:

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

这将是类似于JavaScript的

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

现在,当然,这不会工作OOTB。我在想这样的事情:

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 
} 

这个工程。但我希望能得到一个更好的模式的建议,因为它不是很优雅,也不是真正使用酷的Tcl功能。主要我想摆脱手动呼叫anon_run

回答

11

在Tcl 8.5中,可以使用apply命令。 (!推荐)

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

当然,如果你正在构建你的回调为命令前缀,那么你可以这样做:如果你使用8.4或之前

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 
}] 

,你需要的code from the Tcler's Wiki作为替代品,但请注意,这些解决方案仅在语义上相当(最好);他们不是性能等效的。

+0

另请注意,与JavaScript不同,它不会执行闭包。在Tcl中,闭包在语义上很棘手,因为它们实际上不适合于Tcl的数据类型模型,并且上述的lambda术语使得这个问题特别明显(这不是程序的大问题;仅仅是一个简单的编程问题)。 – 2010-07-13 08:22:20

+0

我很欣赏详细而且很好解释的答案。 – 2010-07-13 09:37:49

+0

我实际上已经为我的一个项目黑了一个[有限形式的闭包](https://chiselapp.com/user/kbk/repository/tclquadcode/artifact/9cd98bc023dd3ef1?ln=353,382)。 – 2015-12-23 19:25:11