All problems in computer science can be solved by another level of indirection. [1]
最近在拿Mathematica做一些小东西的时候发现CurrentValue
等函数在动态中刷新不受Refresh
等方式影响。比如
1 | Dynamic[Refresh[CurrentValue["MousePosition"], None]] |
输出会不断刷新,并不受Refresh[□, None]
结构控制。
另一方面,同样被设计为“过分敏感”的Clock
则受Refresh
控制,
1 | Dynamic[Refresh[Clock[]], None]] |
其输出则不会更新。
鉴于文档中并没有提到过这个问题,我个人认为这是一个bug。不过几个Current
开头的函数都有这个问题,包括CurrentImage
、CurrentNotebookImage
、CurrentScreenImage
,或许这其实是这类函数的一个feature也说不定。然而,出于某些应用场合的需求,我希望这些函数能像其它动态一样受控,这篇文章也因此而来。
当然,前面的例子太过“平凡”了,直接使用静态输出就没有那么多事了。如果我们考虑一个定时刷新的光标位置,那么按照一般的写法,可能写成
1 | Dynamic[CurrentValue["MousePosition"], UpdateInterval -> 1] |
但正如前面指出的,上面这段代码并不能正常地工作。要解决这个问题,实际要引入一个受控的中间层,来间接表示CurrentValue["MousePosition"]
。正如文档中所提到的,通过组合TrackedSymbols
和UpdateInterval
,我们可以精确控制只受符号变化影响的动态更新。再借助DynamicWrapper
同步受控符号与CurrentValue
表达式即可。最终我们得到
1 | DynamicModule[{p}, |
至此,CurrentValue
等动态刷新无法控制的问题圆满解决。
2019年1月22日补充:
这大概确实是一个bug,在SE上的这个问题中作者表示已经将这一情况向Wolfram公司提出了。