Javascript ES6:实现展开函数生成器
我正在尝试重构这段代码,它定义了一个Javascript ES6:实现展开函数生成器,javascript,ecmascript-6,functional-programming,generator,Javascript,Ecmascript 6,Functional Programming,Generator,我正在尝试重构这段代码,它定义了一个展开函数,并使用它来生成计数函数,该函数用数字填充数组,直到计数为止。我不想调用count(100)而是想把count变成一个生成器,可以通过调用next()任意使用它 function unfold (fn, state) { return fn( (value, nextState) => { return [ value, ...unfold (fn, nextState)] },
展开
函数,并使用它来生成计数
函数,该函数用数字填充数组,直到计数为止。我不想调用count(100)
而是想把count变成一个生成器,可以通过调用next()
任意使用它
function unfold (fn, state) {
return fn(
(value, nextState) => {
return [ value, ...unfold (fn, nextState)]
},
()=>[],
state
);
}
function count (max) {
return unfold(
(next, done, state)=>{
return state >= max ?
done() :
next(state, state +1)
},
0
);
}
这里的流程已经有点难以理解,我很难弄清楚收益率报表的流程应该如何工作。我想生成结果数组,即unfold
函数return[value,…unfold(fn,nextState)]
的第4行,但不确定如何将该结果一直传递到count函数
这就是我到目前为止得到的结果,但它只返回一个包含一个生成器的生成器,然后在几个下一个调用后结束:
function * _unfold (fn, base) {
yield * fn(
(value, nextState)=>([ value, ..._unfold (fn, nextState)]),
base
)
return [];
}
function * count (max) {
yield * _unfold(
compress,
0
);
return 0;
}
function * compress (next, state) {
yield next(state, state +1)
return null;
}
我想向您展示一个尽可能接近FP中原始展开实现的实现。希望从那里您可以使用命令生成器实现它
以下是展开器的第一个版本:
unfoldr = f => state => {
const go = ([x, state_]) =>
state_ === undefined
? []
: arrCons(x) (go(f(state_)));
// ^^^^^^^^^^^^^ strictly evaluated
return go(f(state));
};
unfoldr = f => state => {
const go = ([x, state_]) =>
state_ === undefined
? []
: arrCons(x) (thunk(() => go(f(state_))));
return go(f(state));
};
展开是一个内在无限的过程,因此你需要懒散来阻止它。更准确地说,你需要一个函数来构建这个结构,它的第二个参数是非严格的arrCons
在这两个参数中都可能是非严格的,因为它所做的只是将它们存储在一个类似成对的数据类型中。然而,Javascript是经过严格评估的
让我们假设我们有一个函数thunk
,它向Javascript引入了一个隐式thunk,也就是说,一个空函数,您可以在没有括号的情况下调用它,就像对象上的惰性getter一样。它只接受一个普通的空函数,并将其转换为隐式函数。这是我们更新的展开器
:
unfoldr = f => state => {
const go = ([x, state_]) =>
state_ === undefined
? []
: arrCons(x) (go(f(state_)));
// ^^^^^^^^^^^^^ strictly evaluated
return go(f(state));
};
unfoldr = f => state => {
const go = ([x, state_]) =>
state_ === undefined
? []
: arrCons(x) (thunk(() => go(f(state_))));
return go(f(state));
};
现在我们模拟了非严格求值,递归步骤中的表达式的求值刚好足够,即简化为[x,Thunk]
这就是一切。请注意,我们使用[]
表示基本情况,从而表示展开过程的结束。我们更应该用标记的联合来编码这种行为,即选项
/可能
类型。但是为了简单起见,我将实现保持原样
下面是通过定义斐波那契序列来使用unfover
的示例:
const arrCons = head => tail =>
[head, tail];
const unfoldr = f => state => {
const go = ([x, state_]) =>
state_ === undefined
? []
: arrCons(x) (thunk(() => go(f(state_))));
return go(f(state));
};
const fibs = unfoldr(
([x, y]) => [x, [y, x + y]]) ([0, 1]);
const main = fibs[1] [1] [1] [1] [1] [1] [1] [1] [1] [1]; // [55, Thunk]
main[0]; // 55
下面是使用thunk
返回代理的完整实现:
const thunk=f=>
新代理(f,新ThunkProxy(f));
const THUNK=“scriptum_THUNK”;
类ThunkProxy{
建造师(f){
this.memo=未定义;
}
应用(g,that,args){
如果(this.memo==未定义)
this.memo=g();
返回此.memo(…args);
}
定义属性(g,k,描述符){debugger;
如果(this.memo==未定义)
this.memo=g();
Object.defineProperty(this.memo,k,descriptor);
返回true;
}
得到(g,k){
如果(this.memo==未定义)
this.memo=g();
如果(k==THUNK)
返回true;
else if(k==Symbol.toPrimitive)
return()=>this.memo;
否则如果(k==“valueOf”)
return()=>this.memo;
否则返回此。备忘录[k];
}
has(g,k){
如果(this.memo==未定义)
this.memo=g();
在这个备忘录中返回k;
}
集合(g、k、v){
如果(this.memo==未定义)
this.memo=g();
此.memo[k]=v;
返回true;
}
}
常数arrCons=头=>尾=>
[头,尾];
常量arrunbover=f=>state=>{
常数go=([x,状态])=>
状态==未定义
? []
:arrCons(x)(thunk(()=>go(f(state)));
返回go(f(state));
};
常数fibs=arrunfor(
([x,y])=>[x[y,x+y]])([0,1]);
const main=fibs[1][1][1][1][1][1][1][1];//[55,Thunk]
console.log(main[0])代码>