closures - Tcl:惯用的[关闭]
问题描述
从tcl
8.6 开始,什么是惯用形式或closure
?
已发布的模式看起来令人困惑,如下所示。
例子:
#!/usr/bin/env tclsh
::oo::class create Main {
method ensurePath {url args} {
# closure definition, takes time to recognize
set performPath [list my performPath $url {*}$args]
if {0} {
# closure application, can reduce needless noise?
{*}$performPath alpha beta
} elseif {1} {
{*}$performPath omega gamma
} else {
# no performPath
}
}
method performPath {url args} {
puts "[self class]::[self method] {$args}"
}
}
set main [Main new]
$main ensurePath url one two
输出:
::Main::performPath {one two omega gamma}
解决方案
AFAIK,没有惯用的方法来指定 Tcl 中的闭包。虽然闭包所做的事情可以在 Tcl 中模拟,但核心概念与 Tcl 是正交的。
经典的加法器闭包示例(来自Wikipedia)
function add(x)
function addX(y)
return y + x
return addX
variable add1 = add(1)
variable add5 = add(5)
assert add1(3) = 4
assert add5(3) = 8
可以用 Tcl 写成
proc add {name x} {
interp alias {} $name {} ::tcl::mathop::+ $x
}
add add1 1
add add5 5
add1 3
# => 4
add5 3
# => 8
这个“闭包”没有可变状态,但可以修复。这是(一种方法*)Paul Graham 的“累加器生成器”:
proc foo {name n} {
set int [interp create]
$int eval set n $n
$int eval {proc _foo i {incr ::n $i}}
interp alias {} $name $int _foo
}
但是那个不允许共享状态......等等。
我认为在 Tcl 中处理闭包的最佳方法是确定闭包为什么有用,并查看是否没有 Tcl 习惯用法可以做到这一点。像这样的闭包并不是真正的 Tcl 事情。
*) 这是另一个,我不知道是否应该考虑这个更好。
proc _foo i {
set n $i
while 1 {
incr n [yield $n]
}
}
proc foo {name n} {
coroutine $name _foo $n
}
推荐阅读
- python - 如何根据列值比较在 python 中过滤 Pandas 数据框?
- sql - 如何从包含另一个查询作为字符串的 Excel/vba 传递 SQL 查询
- java - Spring Cloud Gateway 不适用于 @Bean DiscoveryClientRouteDefinitionLocator
- c# - C# Socket 监听器不绑定到端口
- python - argparse,但用于标准输入
- php - Wordpress / 在自己的插件中添加几个输入
- android-studio - Android Studio:Gradle 构建任务在哪里定义?
- groovy - Groovy:通过数组列表中的特定标签查找最便宜的价格
- c# - 重构嵌套的 foreach 语句
- json - 从 json 数据填充的下拉列表