一段代码告诉你面向对象和λ演算本质相同
发布于 2 年前 作者 dou4cc 1939 次浏览 最后一次编辑是 1 年前 来自 分享
'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 不动点组合子好像很普通啊,为什么你们老拿它说事?

@dou4cc 搞scheme的觉得普通啊

事实是基本没人看得懂

自己写的过两年你自己也看不懂啊

这基本属于花样炫技…

嗯 可以再整复杂点 然后就是js版源码加密了

@guenchi

事实是基本没人看得懂

就服你。

自己写的过两年你自己也看不懂啊

我还看得懂,真谢谢你。

回到顶部