一段代码告诉你面向对象和λ演算本质相同
'use strict'; //ES.next
const $ = do{
let top=this;
const init = (target, ...keys) => do{
try{
typeof target === 'function'
? target(...keys)
: target[keys[0]];
}catch(error){
console.error(error);
}
};
const isScope = target => typeof target === 'object' && target !== null || typeof target === 'function';
const new_scope = (old, new_match, value) => (...matches) =>
matches.length === 1 && matches[0] === new_match
? value
: init(old, ...matches);
const def = (...matches) => value => {
const def = (scope, value, ...matches) =>
new_scope(scope, matches[0],
matches.length > 1
? def(init(scope, matches[0]), value, ...matches.slice(1))
: value
);
top = def(top, value, ...matches);
};
def('def')(def);
match => do{
const $ = scope => (...matches) => do{
const value=init(scope, ...matches);
isScope(value)
? $(value)
: value;
};
match === undefined
? undefined
: $(top)(match);
};
};
$('Math')('sqrt')(16);
//4
$('def')('Math', 233)(1);
//undefined
$('Math')(233);
//1
$('Math')('233');
//undefined
$('Math')('sqrt')(16);
//4
$('def')('Math', 233, 'test')(2);
//undefined
$('Math')(233);
//[Function]
$('Math')(233)('test');
//2
$('Math')(233)(233);
//undefined
$('def')('Math', 'sqrt', 16)('^_^');
//undefined
$('Math')('sqrt')(16);
//^_^
$('Math')('sqrt')(54397632289);
//233233
$('def')(undefined)('T_T');
//undefined
$(undefined);
//undefined
$('def')('a')(x => x + 6);
//undefined
$('a')(660);
//666
$('def')('b')($('a'));
//undefined
$('def')('b', 660)('^_^');
//undefined
$('b')(660);
//^_^
$('a')(660);
//666
$('b')('FP is cool. +1008');
//FP is cool. +10086
16 回复
没有看懂,楼主能否加点文字解说啊
@kolyjjj 你可以把上述代码用Babel编译成ES5在浏览器或node上试一试。
@kolyjjj 要把do表达式的转换打开。
看结果楼主应该是用ES6实现了一些函数式的特性 面向对象和λ演算不是一个层级的东西吧,要说本质的话应该是图灵机和λ演算等价
@ravenwang 我所指的是object的逐层getter和lambda演算的柯里化本质相同。
@ravenwang “等价”和“本质相同”意思不同。
@dou4cc 我贴到了http://babeljs.io/repl/,结果出错了。楼主还是写一篇渐进点的博客吧,讲讲什么是“object的逐层getter”以及lambda演算的柯里化。
@kolujjj 这是ES6版本,可以直接运行:
'use strict'; //ES6
const λ = (()=>{
let top=this;
const init = (target, ...keys) => (()=>{
try{
return typeof target === 'function' ? target(...keys) : target[keys[0]];
}catch(error){
console.error(error);
}
})();
const isScope = target => typeof target === 'object' && target !== null || typeof target === 'function';
const new_scope = (old, new_match, value) => (...matches) =>
matches.length === 1 && matches[0] === new_match ? value : init(old, ...matches);
const def = (...matches) => value => {
const def = (scope, value, ...matches) =>
new_scope(scope, matches[0],
matches.length > 1 ? def(init(scope, matches[0]), value, ...matches.slice(1)) : value
);
top = def(top, value, ...matches);
};
def('def')(def);
return match => (()=>{
const $ = scope => (...matches) => (()=>{
const value=init(scope, ...matches);
return isScope(value) ? $(value) : value;
})();
return match === undefined ? undefined : $(top)(match);
})();
})();
λ('Math')('sqrt')(16);
//4
λ('def')('Math', 233)(1);
//undefined
λ('Math')(233);
//1
λ('Math')('233');
//undefined
λ('Math')('sqrt')(16);
//4
λ('def')('Math', 233, 'test')(2);
//undefined
λ('Math')(233);
//[Function]
λ('Math')(233)('test');
//2
λ('Math')(233)(233);
//undefined
λ('def')('Math', 'sqrt', 16)('^_^');
//undefined
λ('Math')('sqrt')(16);
//^_^
λ('Math')('sqrt')(54397632289);
//233233
λ('def')(undefined)('T_T');
//undefined
λ(undefined);
//undefined
λ('def')('a')(x => x + 6);
//undefined
λ('a')(660);
//666
λ('def')('b')(λ('a'));
//undefined
λ('def')('b', 660)('^_^');
//undefined
λ('b')(660);
//^_^
λ('a')(660);
//666
λ('b')('FP is cool. +1008');
//FP is cool. +10086
@kolyjjj 之所以不用$
而改成λ
是因为会和有些浏览器控制台的预置函数冲突。
@kolyjjj Babel的在线转换环境不干净,可能和jQuery冲突了。
@kolyjjj 一楼发的代码是对的,结果各种冲突没能运行,后来发的ES6代码有点笔误,真的很抱歉,已经改正。
js版不动点组合子Y?
@guenchi 当年我还小。
@guenchi 不动点组合子好像很普通啊,为什么你们老拿它说事?