gpt4 book ai didi

closures - Tcl:惯用语

转载 作者:行者123 更新时间:2023-12-01 05:02:18 25 4
gpt4 key购买 nike

Tcl 有 applylambda , 但没有闭包

tcl 8.6 开始,什么是惯用形式或闭包

已发布 patterns看起来很困惑,下面的也是如此。

例子:

#!/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}

最佳答案

Tcl 不会完全关闭,但它可以针对关键用例进行有限版本的关闭;如果您看到 {*} 应用于命令的第一个单词,这就是正在发生的事情。例如,您正在执行 (object) 回调 用例。这很简单:

set performPath [namespace code [list my performPath $url {*}$args]]

(命名空间代码确保回调将在正确的命名空间中被评估,即使从对象外部运行也是如此。)

我们甚至可以通过定义辅助过程来使它更整洁:

proc ::oo::Helpers::callback {method args} {
tailcall namespace code [list my $method {*}$args]
}
set performPath [callback performPath $url {*}$args]

同样,变量捕获用例也可以完成。这是假设所有变量都不是数组的最简单版本:

proc closure {body} {
set binding {}
foreach v [uplevel 1 info locals] {
upvar 1 $v var
if {[info exists var]} {
lappend binding [list $v $var]
}
}
return [list apply [list $binding $body [uplevel 1 namespace current]]]
}

演示如何使用它:

proc foo {n} {
set result {}
for {set i 1} {$i <= $n} {incr i} {
lappend result [closure {
puts "This is $i of $n"
}]
}
return $result
}
foreach c [lreverse [foo 10]] {
{*}$c
}

(处理数组和参数使这变得更加复杂。)

如果您需要在“闭包”中修改状态,那么您需要使用对象或协程来保存状态。它们中的任何一个的主要问题是您需要在完成后明确清理生成的命令;标准 Tcl 不会垃圾收集未使用的命令。

关于closures - Tcl:惯用语 ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50453363/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com