所有示例都使用Ramda
as _
(很清楚示例上下文中的方法)和kefir
as frp
(与 bacon.js 中几乎相同的 API)
我有一个流,它描述了位置的变化。
var xDelta = frp
.merge([
up.map(_.multiply(1)),
down.map(_.multiply(-1))
])
.sampledBy(frp.interval(10, 0))
.filter();
+1
当我按下UP
键和-1
on时它会发出DOWN
。
为了获得scan
这个增量的位置
var x = xDelta
.scan(_.add)
.toProperty(0);
这是预期的工作。但我想限制x
from 0
to的值1000
。
为了解决这个问题,我找到了两个解决方案:
更改功能
scan
var x = xDelta.scan(function (prev, next) { var newPosition = prev + next; if (newPosition < 0 && next < 0) { return prev; } if (newPosition > 1000 && next > 0) { return prev; } return newPosition; }, 0);
看起来还可以,但后来随着新规则的引入,这种方法会越来越多。所以我的意思是它看起来不像可组合和 FRPy。
我有
current
立场。和delta
。我想申请delta
,current
只要current after applying
不会超出限制。current
取决于delta
delta
取决于current after applying
current after applying
取决于current
所以它看起来像循环依赖。但我使用
flatMap
.var xDelta = frp .merge([ up.map(_.multiply(1)), down.map(_.multiply(-1)) ]) .sampledBy(frp.interval(10, 0)) .filter(); var possibleNewPlace = xDelta .flatMap(function (delta) { return x .take(1) .map(_.add(delta)); }); var outOfLeftBoundFilter = possibleNewPlace .map(_.lte(0)) .combine(xDelta.map(_.lte(0)), _.or); var outOfRightBoundFilter = possibleNewPlace .map(_.gte(1000)) .combine(xDelta.map(_.gte(0)), _.or); var outOfBoundFilter = frp .combine([ outOfLeftBoundFilter, outOfRightBoundFilter ], _.and); var x = xDelta .filterBy(outOfBoundFilter) .scan(_.add) .toProperty(0);
您可以在iofjuupasli/capture-the-sheep-frp查看完整的代码示例
它正在工作演示gh-pages
它有效,但使用循环依赖可能是反模式。
有没有更好的方法来解决 FRP 中的循环依赖?
第二个更一般的问题
Controller
可以从两个中读取一些值,并根据Model
它的值更新它们。
所以依赖项看起来像:
---> Model
Controller ---|
---> Model
FRP 没有Controller
. 所以Model
value 应该从 other 以声明方式计算Model
。但是如果Model1
从另一个Model2
相同的计算,那么Model2
计算从Model1
?
Model ----->
<----- Model
例如两个具有碰撞检测的玩家:两个玩家都有position
和movement
。movement
第一个玩家取决于第二个玩家,position
反之亦然。
我对所有这些东西还是新手。经过多年的命令式编码,开始以声明式 FRP 风格思考并不容易。可能我错过了一些东西。