我正在学习马丁·奥德斯基的反应规划原理。当谈到一个简单玻璃钢框架的实现时,他在一开始给出了一个使用StackableVariable(即DynamicVairable)来跟踪当前更新的信号的方法,这一点我可以理解。但是在幻灯片的末尾,他提到了一个更清晰的解决方案是使用隐式参数而不是DynamicVariable。有人能告诉我怎么做吗?
发布于 2016-10-30 21:20:46
到幻灯片的链接对我没有用。当我尝试搜索它时,我现在使用1作为参考。
动态变量是一个线程局部变量,它保存当前计算什么信号的状态。这是必要的,以便信号的应用方法可以访问这些信息。让我们考虑下面的示例代码:
val a: Signal[Int] = ???
val b: Signal[Int] = ???
val xPlusY: Signal[Int] = Signal(a() + b())在这里,当调用a()时,它将自己添加到当前计算信号的依赖项列表中。由于其他任何地方都无法访问这些信息,因此我们基本上使用线程本地a.k.a。全局变量
这个解决方案有一些问题。例如,如果不在任何a()中,我们也可以调用Signal()。另外,我们必须使用一个全局变量。
解决方案是通过一个隐式参数将此信息提供给a():我们将签名更改为
Signal[T]#apply(): T至
Signal[T]#apply()(implicit triggeredBy: Signal[_])(请注意,我们可能希望使用一些新类型的TriggeredBy来封装一个信号)
这样,该方法的实现将可以访问其原始信号,而不需要全局/线程局部变量。
但现在我们必须以某种方式提供这个隐含的信息。选项之一是将信号创建函数的签名更改为
def Signal.apply[T](fun: => T): Signal[T]至
def Signal.apply[T](fun: Signal[_] => T): Signal[T]不幸的是,我们的示例代码的语法必须改变,因为我们必须提供一个函数而不是一个主体:
val xPlusY: Signal[Int] = Signal { implicit triggeredBy => a() + b() }对于这个问题,有几种解决办法:
Signal.apply签名:
def Signal.applyT:SignalT
然后能够再次编写Signal(a() + b())。Signal(a() + b())的代码转换为Signal.internalApply(implicit triggeredBy => a() + b())代码。这意味着,Signal.apply现在是一个宏。这就是scala.rx3.所走的道路,从使用的角度来看,它运行得很好。这也允许我们再次编写Signal(a() + b())。更新:指向隐式函数的更新链接,解释到更详细的博客文章
https://stackoverflow.com/questions/39928480
复制相似问题