hwencc

其他:

函数式编程(一):纯函数

函数式编程(二):curry

 

前面说到 curry,而 curry 与 compose(组合)是一对好基友,curry 函数的很大价值体现在它对于 compose 的友好性。组合的思想在于把小的单元逻辑合成一个程序,1+1>2。

 

在数学里,函数 f 和 g 的组合定义为 f( g(x) ),在 JavaScript 中就是这样了

var compose = function(f, g) {
	return function(x) {
		return f(g(x));
	};
};

可以看成 x 在函数 f,g之间通过“管道”传输,来看一个例子。

var head = function(x) {
	return x[0];
};
var reverse = reduce(function(acc, x) {
	return [x].concat(acc);
}, []);
var last = compose(head, reverse);
last([\'jumpkick\', \'roundhouse\', \'uppercut\']);
//=>	\'uppercut\'

你是否注意到 reverse 函数最先被应用?这很重要,函数是从右向左应用的。(从右往左执行更能反映数学上的定义)。组合函数有一个强大的特性——结合律。这意味着任何一个函数分组都可以拆开来,然后再以它们自己的组合方式打包在一起,这给我们带来了强大的灵活性。

var toUpperCase = function(x) {
	return x.toUpperCase();
};
var exclaim = function(x) {
	return x + \'!\';
};

compose(toUpperCase, compose(head, reverse));
// 或者
compose(compose(toUpperCase, head), reverse);

//因为如何为 compose 的调用分组不重要,所以结果都是一样的。这也让我们有//能力写一个可变的组合(variadic compose),用法如下:
// 前面的例子中我们必须要写两个组合才行,但既然组合是符合结合律的,我们// 就可以只写一个,
// 而且想传给它多少个函数就传给它多少个,然后让它自己决定如何分组。
var lastUpper = compose(toUpperCase, head, reverse);

lastUpper([\'jumpkick\', \'roundhouse\', \'uppercut\']);
//=> \'UPPERCUT\'


var loudLastUpper = compose(exclaim, toUpperCase, head, reverse)

loudLastUpper([\'jumpkick\', \'roundhouse\', \'uppercut\']);
//=> \'UPPERCUT!\'

//	或
var	last	=	compose(head,	reverse);
var	angry	=	compose(exclaim,	toUpperCase);
var	loudLastUpper	=	compose(angry,	last);
//	更多变种...

 

关于如何组合,并没有标准的答案——我们可以按自己喜欢的方式搭乐高积木。一般最佳实践是让组合可重用。

 

#compose与curry

来看一个例子:

HTML代码部分:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.11/require.min.js"></script>
	<script src=\'flickr.js\'></script>
</head>
<body>
	
</body>
</html>

 

js部分:

requirejs.config({
	paths: {
		ramda: \'https://cdnjs.cloudflare.com/ajax/libs/ramda/0.13.0/ramda.min\',
		jquery: \'https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min\'
	}
});

// prop 函数的实现
// var prop = _.curry(function(property, object){
//   return object[property];
// });

require([
		\'ramda\',
		\'jquery\'
	],
	function(_, $) {
		//utils
		var Impure = {
			getJSON: _.curry(function(callback, url) {
				$.getJSON(url, callback);
			}),

			setHtml: _.curry(function(sel, html) {
				$(sel).html(html);
			})
		};

		var img = function(url) {
			return $(\'<img/>\', {
				src: url
			});
		};

		var trace = _.curry(function(tag, x) {
			console.log(tag, x);
			return x;
		});

		var url = function(t) {
			return \'https://api.flickr.com/services/feeds/photos_public.gne?tags=\' + t + \'&format=json&jsoncallback=?\';
		};

		var mediaUrl = _.compose(_.prop(\'m\'), _.prop(\'media\')); 

		var srcs = _.compose(_.map(mediaUrl), _.prop(\'items\'));

		var images = _.compose(_.map(img), srcs);

		var renderImages = _.compose(Impure.setHtml(\'body\'), images);

		var app = _.compose(Impure.getJSON(trace(renderImages), url);
		// var app = _.compose(Impure.getJSON(trace(trace(\'response\')), url);

		app(\'cats\');

});

通过 curry 与 组合 搭建起一个简单的应用,请求 Flickr 图片,并加载到页面上。。

分类:

技术点:

相关文章:

  • 2021-08-20
  • 2022-03-03
  • 2022-01-25
  • 2021-06-11
  • 2019-10-27
  • 2022-01-13
  • 2018-03-13
猜你喜欢
  • 2018-07-18
  • 2019-09-26
  • 2022-01-01
  • 2022-02-20
  • 2021-03-08
  • 2021-08-28
相关资源
相似解决方案