6

我在 Scala 中实现了一个 FRP 框架,我似乎遇到了问题。出于某种想法,这个问题我决定限制我的框架的公共接口,因此只能在“现在”中评估行为,即:

behaviour.at(now) 

这也符合 Conal 在 Fran 论文中的假设,即仅在增加的时间对行为进行评估/采样。它确实限制了 Behaviors 的转换,但除此之外,我们发现自己在代表某些输入的 Behaviors 中存在巨大问题:

val slider = Stepper(0, sliderChangeEvent) 

使用此行为,评估未来值将是不正确的,评估过去值将需要无限量的内存(必须存储“滑块”事件中使用的所有事件)。

鉴于此限制,我对行为的“快照”操作规范有疑问。我的问题最好用一个例子来解释(使用上面提到的滑块):

val event = mouseB // an event that occurs when the mouse is pressed 
val sampler = slider.snapshot(event) 
val stepper = Stepper(0, sampler) 

我的问题是,如果在执行此代码时发生了“mouseB”事件,那么“步进器”的当前值将是“滑块”的最后一个“样本”(最后一次发生时的值)。如果最后一次发生的时间是过去,那么我们最终将使用过去的时间来评估“滑块”,这违反了上面的规则集(以及您最初的假设)。我可以看到几种解决此问题的方法:

  1. 我们“记录”过去(在事件中保留所有过去发生的事件)允许评估过去时间的行为(使用无限量的内存)
  2. 我们修改“快照”以采用时间参数(“此时间后的样本”)并强制该时间 >= 现在
  3. 在一个更古怪的举动中,我们可以以某种方式将 FRP 对象的创建限制为程序的初始设置,并且仅在此设置完成后才开始处理事件/输入

我也可以简单地不实现'sample'或删除'stepper'/'switcher'(但我真的不想做这两件事)。有人对此有任何想法吗?我在这里误解了什么吗?

4

3 回答 3

3

据我所知,您担心竞争条件:如果在代码执行时发生事件会发生什么

纯函数式代码不希望知道它会被执行。函数式技术在纯粹的环境中处于最佳状态,因此执行代码的顺序无关紧要。摆脱这种困境的一种方法是假装每次更改都发生在一段敏感的(可能是内部的)命令式代码中;假设 FRP 框架中的任何功能声明发生在 0 时间,因此在声明期间不可能更改某些内容。

没有人应该在一段声明行为和事物的代码中睡觉,或者真的做任何时间敏感的事情。本质上,与 FRP 对象一起工作的代码应该是纯的,那么你就没有任何问题。

这并不一定排除在多个线程上运行它,但为了支持您可能需要重新组织内部表示。欢迎来到 FRP 库实现的世界——我怀疑您的内部表示会在此过程中多次波动。:-)

于 2012-03-09T03:47:49.217 回答
3

哦,我明白你现在的意思了。

我认为,您的“您只能在‘现在’取样”的限制还不够严格。它需要更强大一点,以避免回顾过去。由于您使用的是 的环境概念now,因此我将根据它来定义行为构造函数(只要now不能仅通过执行定义来推进,根据我的最后一个答案,这会变得混乱)。例如:

Stepper(i,e)是一个行为,其值i在区间内[now,e1](其中是aftere1的第一次出现的时间),以及最近出现的afterward 的值。enowe

有了这个语义,你对那个让你陷入这个难题的价值的预测就stepper被取消了,步进器现在的值为 0。我不知道这个语义是否适合你,但对我来说似乎很自然。

于 2012-03-09T11:15:44.913 回答
0

我对你的困惑感到困惑。我看到的方式是,Stepper每当事件发生时,都会将行为“设置”为新值。因此,会发生以下情况:

事件mouseB发生的那一刻,slider将读取行为的值 ( snapshot)。这个值将被“设置”到行为stepper中。

因此,确实Stepper会“记住”过去的价值观;关键是它只记住过去的最新值,而不是所有内容。

从语义上讲,最好建模Stepper为 luqui 提出的函数。

于 2012-03-10T08:25:00.563 回答