什么时候a => f(a)不等于f?

bba*_*ton 6 javascript functional-programming curry lodash

lodash的新手,并尝试使用它来获得更多的了解。我不了解以下代码的行为。

在了解到的arity参数之后_.curry,我得到了一个代码片段,该片段产生的结果对我来说似乎很奇怪。

const words = ['jim', 'john'];
const pad10 = words =>
    _.map(words, word => _.pad(word, 10));

console.log(pad10(words)); // [ '   jim    ', '   john   ' ]

const flipMap = _.flip(_.map);
const flipPad = _.flip(_.pad);

const curriedFlipMap = _.curry(flipMap, 2);

const pad10v2 = curriedFlipMap(word => flipPad(' ', 10, word));

console.log(pad10v2(words)); // [ '   jim    ', '   john   ' ]

const curriedFlipPad = _.curry(flipPad, 3);
const padWord10 = curriedFlipPad(' ', 10);
const pad10v3 = curriedFlipMap(word => padWord10(word));

console.log(pad10v3(words)); // [ '   jim    ', '   john   ' ]

const pad10v4 = curriedFlipMap(padWord10);
console.log(pad10v4(words)); // [ 'jim,john', 'jim,john' ]
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

我不了解最后一个console.log的输出。在我看来,当我需要一个arg函数时,我只是用f替换了=> f(a)。

Aad*_*hah 2

f是的,JavaScript 中的和之间是有区别的a => f(a)。考虑以下示例:

const array = (...args) => args;

const arrayEta = a => array(a);

console.log(array(1, 2, 3)); // [1, 2, 3]

console.log(arrayEta(1, 2, 3)); // [1]
Run Code Online (Sandbox Code Playgroud)

你看到问题了吗?当我调用arrayEta(1, 2, 3)它时,它会扩展为(a => array(a))(1, 2, 3)beta 减少为,array(1)因为23从未使用过。然而,非 eta 扩展版本是array(1, 2, 3). 这是您的代码的问题:

const words = ["jim", "john"];

const flipMap = _.flip(_.map);
const flipPad = _.flip(_.pad);

const curriedFlipMap = _.curry(flipMap, 2);
const curriedFlipPad = _.curry(flipPad, 3);

const padWord10 = curriedFlipPad(" ", 10);

const pad10v4 = curriedFlipMap((...args) => {
    console.log(args); // args is an array of 3 arguments
    return padWord10(...args);
});

console.log(pad10v4(words)); // ["jim,john", "jim,john"]
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

请注意,args 是一个包含三个参数的数组:word、index 和 array。因此,curriedFlipMap(padWord10)eta 实际上等于curriedFlipMap((word, index, array) => padWord10(word, index, array))。它不等于 eta curriedFlipMap(word => padWord10(word))

因此,您的函数调用减少如下:

  padWord10("jim", 0, ["jim", "john"])
= curriedFlipPad(" ", 10)("jim", 0, ["jim", "john"])
= _curry(flipPad, 3)(" ", 10)("jim", 0, ["jim", "john"])
= _.pad(["jim", "john"], 0, "jim", 10, " ")
= _.pad(["jim", "john"], 0, "jim")
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,您为函数提供了_.pad5 个参数,其中它忽略了最后 2 个参数。因此,它会转换["jim", "john"]为字符串,然后向其添加填充。

无论如何,解决方案是在这种情况下不进行 eta 转换。顺便说一句,如果您想使用 Lodash 进行函数式编程,请lodash/fp改为使用。