我正在尝试使用 after 闪烁标签。 最终我得到了我想要的,但我发现了一件事, 这让我很困惑:
set data(tm) [after 500 {on-tick data}]
set $data(tm) [after 500 {on-tick data}]
两种变体(带美元符号和不带美元符号)都按预期工作。 在我看来,这也适用于取消:
after cancel data(tm)
after cancel $data(tm)
为什么会这样?为什么使用与不使用参考没有区别?
对我来说看起来很传统的一对是:
set data(tm) [after 500 {on-tick data}]
after cancel $data(tm)
其他情况很奇怪,并且可能没有按照您的预期进行:
这个:
set $data(tm) [after 500 {on-tick data}]
正在将标记写入数组变量中指定的变量中。这是双重取消引用,并且可能是一个坏主意。预计它会与这种尴尬的形式配对:
after cancel [set $data(tm)]
多年来一直有一个突出的功能请求来支持
$$var
作为一种更轻松地进行双重取消引用的方式,但它在任何人的雷达上的优先级都非常低,因为大多数情况下使用 $ary($var)
或类似的东西更具可读性;当然,这不是同一件事,但它通常可以满足真正的需求(并且使用 upvar 0
来处理其余的事情)。使用数组来管理间接往往会使事情更容易记忆,至少对我来说:
set timers($data(tm)) [after 500 {on-tick data}]
after cancel $timers($data(tm))
Tcl 中的 $
并不意味着“这是一个变量”,而是“现在从这个变量中读取”。 (单个参数 set
做同样的事情;very 老版本的 Tcl 只有这个,没有 $
语法。)
这个:
after cancel data(tm)
可能什么也没做。它正在寻找一个预定事件,其处理程序是文字字符串
data(tm)
。它可能没有找到一个;查找失败时不会发生任何事情。这是因为没有什么麻烦去尝试保留您可能曾经能够查找的所有内容的明确列表,并且过期的计时器事件会被简单地忘记,因为这样更简单并且使内存管理更容易。
如果你完成了:
set data(tm) [after 500 data(tm)]
那么这将被取消......并且对于命令来说也是一个相当奇怪的名称!合法,但很奇怪。