在调用之前按顺序完成所有函数参数 [英] Fulfilling all function arguments in order before invoking

查看:119
本文介绍了在调用之前按顺序完成所有函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解下面的zip函数(特别是invoke函数)是如何变得更加有用的。我得到的问题是,调用方法必须等待左侧和右侧填充,然后才能分派值。必须按顺序调用这些值,以便正确的值被压缩,否则我会考虑执行此操作的咖喱/部分函数。



有什么我可以使用的,可以消除这种障碍。

  function zip(state,a,b){
var left = [];
var right = [];

函数invoke(){
if(left.length> 0&& right.length> 0){
state([left.shift(), right.shift()]);


$ b a.foreach(function(v){
left.push(v);
invoke();
});
$ b b.foreach(function(v){
right.push(v);
invoke();
});
}



Bellow是一个满足zip函数的简单例子。

 函数Stream(){
var env = this;
env.subs = [];
env.id = setInterval(function(){
env.subs.forEach(function(f){
f(Math.random());
}); $ b $(b),((Math.random()* 100)+ 500)| 0);
}
Stream.prototype.foreach = function(f){
this.subs.push(f); (v){
console.log(v);
},new Stream(),new Stream());
}
zip

奖励:移除可变数组。

Stream 有某种迭代器,那么可以使用更多的函数式方法>接口,它将列表中的第一个元素和它的继承者分开(就像Haskell列表的构建,你似乎知道它们)。



我知道这个代码更复杂(至少更长),但使用结构变得更加方便:

$ p $ function Promise(resolver){
//你当然知道答应libs当然
//这个不是单子
var subs = [],
res = null;
resolver(function resolve(){
res = arguments;
while(subs.length)subs.shift()。apply(null,res);
});
this.onData = function(f){
if(res)
f.apply(null,res);
else
subs.push(f);
返回此;
};

Promise.all = function(){
var ps = Array.prototype.concat.apply([],arguments);
return new Promise(function(resolve){
var res = [],
l = ps.length;
ps.forEach(function(p,i){$ b $ (函数(){
while(res.length< arguments.length)res.push([]);
for(var j = 0; j< arguments.length; j ++ )
res [j] [i] = arguments [j];
if(--l == 0)
resolve.apply(null,res);
}) ;
});
});
};





 函数Stream() {
//一个异步(随机)列表
var that = this,
interval =(Math.random()* 100 + 500)| 0;
this.first = new Promise(function create(resolve){
that.id = setTimeout(function(){
resolve(Math.random(),new Promise(create));
},interval);
});
}
//这是如何使用流:
Stream.prototype.forEach = function(f){
this.first.onData(function fire(res,next ){
f(res);
next.onData(fire);
});
返回此;
};
Stream.prototype.end = function(){clearTimeout(this.id);返回这个; };

但现在很容易:

 函数zip(){
var res = Object.create(Stream.prototype); //继承Stream接口
res.first =(function create(firsts){
return new Promise(function(resolve){
Promise.all(firsts).onData(function(results ,nexts){
resolve(results,create(nexts));
});
});
})(Array.prototype.map.call(arguments,function (stream){
return stream.first;
}));
return res;
}
zip(new Stream,new Stream).forEach(console.log.bind(console));

基本上我已经将第一个项目等待到Promise模式,其中 Promise.all 具有并行等待功能,您的可变结果数组嵌入到承诺的嵌套列表中。我通过让所有函数都可以处理任意数量的参数,避免了代码重复(对于 left 和 right )。

I'm trying to understand how the following zip function (esp. the invoke function) can be made more functional. The issue I've got is that the invoke method has to wait for both the left and right side to be filled before it can dispatch the values. The values have to be called in order so that the correct values are zipped, otherwise I would consider a curry/partial function to fulfill this.

Is there anything that I could use that could remove this hinderance.

function zip(state, a, b) {
    var left = [];
    var right = [];

    function invoke() {
        if (left.length > 0 && right.length > 0) {
            state([left.shift(), right.shift()]);
        }
    }

    a.foreach(function(v) {
        left.push(v);
        invoke();
    });

    b.foreach(function(v) {
        right.push(v);
        invoke();
    });
}

Bellow is a simple example of what satisfies the zip function.

function Stream() {
    var env = this;
    env.subs = [];
    env.id = setInterval(function() {
        env.subs.forEach(function(f) {
            f(Math.random()); 
        });
    }, ((Math.random() * 100) + 500) | 0);
}
Stream.prototype.foreach = function(f) {
    this.subs.push(f);
}
zip(function(v) {
    console.log(v);
}, new Stream(), new Stream());

Bonus: Removing mutable array.

解决方案

A more functional approach would be possible if the Stream had some kind of iterator interface, that divides the list in the first element and its successors (like Haskell lists are built, you seem to know them).

I know this code is more complex (and at least longer) at first, but using the structures gets more convenient:

function Promise(resolver) {
    // you know better promise libs of course
    // this one is not even monadic
    var subs = [],
        res = null;
    resolver(function resolve() {
        res = arguments;
        while (subs.length) subs.shift().apply(null, res);
    });
    this.onData = function(f) {
        if (res)
            f.apply(null, res);
        else
            subs.push(f);
        return this;
    };
}
Promise.all = function() {
    var ps = Array.prototype.concat.apply([], arguments);
    return new Promise(function(resolve) {
        var res = [],
            l = ps.length;
        ps.forEach(function(p, i) {
            p.onData(function() {
                while(res.length < arguments.length) res.push([]);
                for (var j=0; j<arguments.length; j++)
                    res[j][i] = arguments[j];
                if (--l == 0)
                    resolve.apply(null, res);
            });
        });
    });
};

function Stream() {
    // an asynchronous (random) list
    var that = this,
        interval = (Math.random() * 100 + 500) | 0;
    this.first = new Promise(function create(resolve) {
        that.id = setTimeout(function() {
            resolve(Math.random(), new Promise(create));
        }, interval);
    });
}
// this is how to consume a stream:
Stream.prototype.forEach = function(f) {
    this.first.onData(function fire(res, next) {
        f(res);
        next.onData(fire);
    });
    return this;
};
Stream.prototype.end = function() { clearTimeout(this.id); return this; };

But zipping them is easy now:

function zip() {
    var res = Object.create(Stream.prototype); // inherit the Stream interface
    res.first = (function create(firsts) {
        return new Promise(function(resolve) {
            Promise.all(firsts).onData(function(results, nexts) {
                resolve(results, create(nexts));
            });
        });
    })(Array.prototype.map.call(arguments, function(stream) {
        return stream.first;
    }));
    return res;
}
zip(new Stream, new Stream).forEach(console.log.bind(console));

Basically I've generalized your waiting for the first items into the Promise pattern, where Promise.all features parallel waiting, and your mutable arrays of results into nested lists of promises. And I've avoided code duplication (for left and right) by making all functions work with any number of arguments.

这篇关于在调用之前按顺序完成所有函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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