使用撰写有什么好处?

时间:2016-01-19 13:26:41

标签: javascript functional-programming ramda.js

我正在学习使用Ramda并遇到撰写。但我无法理解它的目的

let value = R.compose( calledThird, calledSecond, calledFirst('hello') );

// vs

let value = calledThird( calledSecond( calledFirst('hello') ) );

纯粹是为了让咖喱干吗?也许...

let curried = R.compose( calledThird, calledSecond, calledFirst );

curried('hello');

还有其他目的吗?

2 个答案:

答案 0 :(得分:11)

你的第二个例子正是它的原因,虽然这实际上与currying没有关系。

功能组合允许您使用更简单的功能构建更复杂的功能。

想象一下,你有一些你需要排序的数据类型,让我们说一些约会。鉴于您已经拥有sortByDate函数和reverse函数,您可以将sortByDateDescending写为

var sortByDateDescending = function(appointments) {
    return reverse(sortByDate(appointments));
}

或在ES6中:

const sortByDateDescending = appointments => reverse(sortByDate(appointments));

这没有错。但如果您使用compose帮助程序编写它,它有几个优点:

var sortByDateDescending = compose(reverse, sortByDate);

首先,它显然更短,当你添加更多功能时,差异会变得更大,特别是使用pre-es6代码。

但更重要的是,这可以让你专注于有意义的事情。你在这里组合功能;最终将通过的数据是目标,但是当您构建新功能时,它主要是分散注意力。

通过这种方式编写,您可以专注于正在进行的操作:您按日期对列表进行排序,然后您正在反转结果。

更加专注于函数式编程的语言使这个更简单,使用不显眼的运算符而不是像compose这样的函数。在Haskell中,等价物看起来像

sortByDateDescending = reverse . sortByDate

但Javascript并没有提供那种优雅。我们所能做的最好的事情就是创建compose(或其顺序反转双胞胎,pipe等函数。)

我的introduction to Ramda帖子提供了更多以这种方式工作的例子。

顺便说一下,干脆是一个完全不同的野兽。这种技术使得在这种组合物中重用功能变得容易得多。但它在这里大多是分散注意力的。如果您有兴趣,我也have a post就此问题。

答案 1 :(得分:1)

斯科特的答案很棒 - 只是想添加一些更现实的例子。

当您看到很多此类模式时,您可以识别改进代码的位置,您可以通过直通函数不断地按摩某些数据:

var list = [3, 4, 1, 2];

list = filterOutEvens(list);
list = sort(list);
list = prependFoo(list);

你可能会想做这样的事情:

[3, 4, 1, 2].filterOutEvens().sort().prependFoo();

但是你记得为了使这成为可能,你必须向Array.prototype添加东西,这绝对是禁止的。

R.compose为您提供了下一个最好的东西(请记住它从右到左):

var processList = R.compose(prependFoo, sort, filterOutEvens);
processList([3, 4, 1, 2]);

如果你想玩它,可以在这里找到完整的例子:



function filterOutEvens(list) {
    return list.filter(function(item) {
        return item % 2 !== 0;
    });
}

function sort(list) {
    // More cleanly use R.sort here instead of native Array.prototype.sort, which operates in-place.
    var diff = function(a, b) { return a - b; };
    return R.sort(diff, list);
}

function prependFoo(list) {
    return list.map(function(item) {
        return 'foo-' + item;
    });
}

var processList = R.compose(prependFoo, sort, filterOutEvens);

var result = processList([3, 4, 1, 2]);
// -> ["foo-1", "foo-3"]

// Display Stackoverflow snippet output.
document.body.innerHTML = JSON.stringify(result, null, 2);

<script src="//cdn.jsdelivr.net/ramda/0.19.1/ramda.min.js"></script>
&#13;
&#13;
&#13;