抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

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开头的函数都有这个问题,包括CurrentImageCurrentNotebookImageCurrentScreenImage,或许这其实是这类函数的一个feature也说不定。然而,出于某些应用场合的需求,我希望这些函数能像其它动态一样受控,这篇文章也因此而来。

当然,前面的例子太过“平凡”了,直接使用静态输出就没有那么多事了。如果我们考虑一个定时刷新的光标位置,那么按照一般的写法,可能写成

1
Dynamic[CurrentValue["MousePosition"], UpdateInterval -> 1]

但正如前面指出的,上面这段代码并不能正常地工作。要解决这个问题,实际要引入一个受控的中间层,来间接表示CurrentValue["MousePosition"]。正如文档中所提到的,通过组合TrackedSymbolsUpdateInterval,我们可以精确控制只受符号变化影响的动态更新。再借助DynamicWrapper同步受控符号与CurrentValue表达式即可。最终我们得到

1
2
3
4
5
6
DynamicModule[{p},
DynamicWrapper[
Dynamic[p, UpdateInterval -> 1, TrackedSymbols :> {}],
p = CurrentValue["MousePosition"]
]
]

至此,CurrentValue等动态刷新无法控制的问题圆满解决。


2019年1月22日补充
这大概确实是一个bug,在SE上的这个问题中作者表示已经将这一情况向Wolfram公司提出了。


  1. https://www2.dmst.aueb.gr/dds/pubs/inbook/beautiful_code/html/Spi07g.html ↩︎

评论