与FRP战斗 [英] Fighting with FRP

查看:159
本文介绍了与FRP战斗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读过FRP,非常兴奋。
它看起来很棒,所以你可以编写更多高级代码,一切都更具组合性等等。

I've read about FRP and was very excited. It looks great, so you can write more high-level code, and everything is more composable, and etc.

然后我试着改写我的从普通的js到培根,只有几百个sloc的小游戏。

Then I've tried to rewrite my own little game with a few hundreds sloc from plain js to Bacon.

我发现不是编写高级逻辑代码,而是实际上用培根打败了。 js及其对原则的遵守。

And I found that instead of writing high-level logic-only code, I actually beating with Bacon.js and its adherence to principles.

我遇到了一些令人头疼的问题,主要是干扰清洁代码

I run into some headache that mostly interfere clean code


  1. .take(1)

  1. .take(1)

而不是获得价值,我应该创建丑陋的结构。

Instead of getting value, I should create ugly constructions.


  1. 循环依赖

有时它们应该是逻辑的。但在FRP中实施它是可怕的

Sometimes they should be by logic. But implementing it in FRP is scary


  1. 活跃状态

即使是bacon.js的创建者也有麻烦用它。

Even creator of bacon.js have troubles with it.

这里的例子是用于证明问题的代码的和平:

As example here is the peace of code to demonstrate the problem:

任务是不允许两个玩家留在同一个地方

Task is to not allow two players stay at same place

用bacon.js实现

Implemented with bacon.js

http://jsbin.com/zopiyarugu/2/edit?js,console

function add(a) {return function(b){return a + b}}
function nEq(a) {return function(b){return a !== b}}
function eq(a) {return function(b){return a === b}}
function always(val) {return function(){return val}}
function id(a){return a}

var Player = function(players, movement, initPos){
    var me = {};
    me.position = movement
        .flatMap(function(val){
            return me.position
                .take(1)
                .map(add(val))
        })
        .flatMap(function(posFuture){
            var otherPlayerPositions = players
                .filter(nEq(me))
                .map(function(player){return player.position.take(1)})
            return Bacon
                .combineAsArray(otherPlayerPositions)
                .map(function(positions){
                    return !positions.some(eq(posFuture));
                })
                .filter(id)
                .map(always(posFuture))
        })
        .log('player:' + initPos)
        .toProperty(initPos);
    return me;
}

var moveA = new Bacon.Bus();
var moveB = new Bacon.Bus();

var players = [];
players.push(new Player(players, moveA, 0));
players.push(new Player(players, moveB, 10));

moveA.push(4);
moveB.push(-4);
moveA.push(1);
moveB.push(-1);
moveB.push(-1);
moveB.push(-1);
moveA.push(1);
moveA.push(-1);
moveB.push(-1);

我要证明的是:


  1. me.positions 依赖自己

  2. 理解这段代码并不容易。 此处是必不可少的实施方案。它看起来更容易理解。我花了很多时间用培根实施。结果我不确定它会按预期工作。

  1. me.positions have dependency on its own
  2. It's not easy to understand this code. Here is imperative implementation. And it looks much easier to understand. I spent much more time with bacon implementation. And in result I'm not sure that it will works as expected.






我的问题:



可能我会错过一些基本的东西。也许我的实现在FRP风格中并非如此?


My question:

Probably I miss something fundamental. Maybe my implementation is not so in FRP style?

也许这段代码看起来不错,它只是不习惯新的编码风格?

Maybe this code looks ok, and it just unaccustomed with new coding style?

或者这个众所周知的问题,我应该选择最好的邪恶?如此描述的FRP麻烦,或OOP的麻烦。

Or this well-known problems, and I should choose best of all evil? So troubles with FRP like described, or troubles with OOP.

推荐答案

我尝试用培根写游戏时遇到过类似的经历和RxJs。具有自我依赖性的东西(如玩家的位置)很难以纯粹的FRP方式处理。

I've had similar experiences when trying to write games with Bacon and RxJs. Things that have a self-dependency (like player's position) are tough to handle in a "pure FRP" way.

例如,在我早期的Worzone游戏中,我包含了一个可变的目标可以查询玩家和怪物位置的对象。

For example, in my early Worzone game I included a mutable targets object that can be queried for positions of players and monsters.

另一种方法是做榆树伙计们:将完整的游戏状态建模为单个属性(或在Elm中调用的信号)并根据该完整状态计算下一个状态。

Another approach is to do as the Elm guys do: model the full game state as a single Property (or Signal as it's called in Elm) and calculate the next state based on that full state.

到目前为止我的结论是FRP不太适合游戏编程,至少是以纯粹的方式。毕竟,可变状态对于某些事情可能是更可组合的方法。在一些游戏项目中,比如Hello World Open赛车,我使用了可变状态,比如用于存储状态的DOM和用于传递事件的EventStreams。

So far my conclusion is that FRP is not so well-suited for game programming, at least in a "pure" way. After all, mutable state might be the more composable approach for some things. In some game projects, like the Hello World Open car race, I've used mutable state, like the DOM for storing state and EventStreams for passing events around.

所以, Bacon.js不是银弹。我建议你找出自己,在哪里申请FRP以及不在哪里!

So, Bacon.js is not a silver bullet. I suggest you find out yourself, where to apply FRP and where not to!

这篇关于与FRP战斗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆