Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
称为变量的Tcl对象方法_Tcl - Fatal编程技术网

称为变量的Tcl对象方法

称为变量的Tcl对象方法,tcl,Tcl,如何将对象方法作为变量执行 oo::class create handlerTest { method onEvent {} { puts "onEvent method" } } set testObj [handlerTest new] #set wrapper {$testObj onEvent} #set wrapper {$testObj::my onEvent} #set wrapper [namespace code {$testObj onEve

如何将对象方法作为变量执行

oo::class create handlerTest {
    method onEvent {} {
        puts "onEvent method"
    }
}

set testObj [handlerTest new]
#set wrapper {$testObj onEvent}
#set wrapper {$testObj::my onEvent}
#set wrapper [namespace code {$testObj onEvent}]
#set wrapper "eval testObj onEvent
#set wrapper {[eval testObj onEvent]}
$wrapper
上述所有尝试似乎都是作为单个命令执行
$wrapper
,而不是带有args的命令

由于我正在使用调用已定义包装的外部库,因此无法更改包装的调用方式(即
{*}$wrapper


有什么方法可以做到这一点吗?

重写命令名本身的唯一方法是通过未知处理程序(默认为在全局命名空间中被称为
unknown
;您可能希望使用该默认值)。在执行此操作时需要注意,因为默认处理程序会执行某些代码需要呈现的操作;使用
rename
稍微移动一下就可以了

# only want special treatment for some commands
set autoexpanded [list $testObj]

# save for later
rename unknown _original_unknown

proc unknown args {
    global autoexpanded
    # if we want to expand the first word...
    if {[catch {lindex $args 0 0} cmd] == 0 && $cmd in $autoexpanded} {
        # delegate to the expanded command (tailcall is perfect here)
        set args [lassign $args cmd]
        tailcall {*}$cmd {*}$args
    } else {
        # delegate to the original unknown
        tailcall _original_unknown {*}$args
    }
}

请注意,这不是一种快速分派机制。只有当命令不存在(速度也很慢,但错误路径从来都不是最优的或经过了大量优化)而导致另一个选项抛出错误时,才使用此选项。

想到的最简单的方法是为别名生成名称并将其放入变量中:

set testObj [handlerTest new]
set wrapper [interp alias {} wrapper[incr wrapperid] {} $testObj onEvent]
$wrapper
=>OneEvent方法

或:

proc theWrapper {} [
    upvar 1 testObj testObj
    tailcall $testObj onEvent
}
set wrapper theWrapper
$wrapper

您不希望使用常规的“扩展所有内容”规则,但一定要小心确保没有无限递归的可能性(在
autoexpanded
变量中列出要执行此操作的现有命令应该很容易)。如果你不走这条路就能做正确的事情,你也希望避免欺骗。谢谢,多纳尔。我假设在命令字符串中没有任何东西可以“欺骗”解释器进行扩展?以前有这样一个黑客(如果我没记错的话,支持itcl),但是它被删除了,因为它是一个丑陋的奇怪的黑客。上面的答案就不那么可怕了!可能的但是速度慢而且有点棘手!我错过什么了吗?如果使用前面的扩展操作调用包装器,
set wrapper[list$testObj onEvent]
不起作用吗?更好的是,使用
tailcall$testObj onEvent
这样helper过程将自己从堆栈中删除。