在调用之前按顺序完成所有函数参数 [英] Fulfilling all function arguments in order before invoking
问题描述
我试图理解下面的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
奖励:移除可变数组。
迭代器
,那么可以使用更多的函数式方法>接口,它将列表中的第一个元素和它的继承者分开(就像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模式,其中 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. Bellow is a simple example of what satisfies the zip function. Bonus: Removing mutable array. A more functional approach would be possible if the I know this code is more complex (and at least longer) at first, but using the structures gets more convenient:
But zipping them is easy now: Basically I've generalized your waiting for the first items into the Promise pattern, where 这篇关于在调用之前按顺序完成所有函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! Promise.all
具有并行等待功能,您的可变结果数组嵌入到承诺的嵌套列表中。我通过让所有函数都可以处理任意数量的参数,避免了代码重复(对于 left 和
right
)。 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();
});
}
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());
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).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; };
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));
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.