【问题标题】:Understanding Ramda.js理解 Ramda.js
【发布时间】:2015-10-15 07:19:53
【问题描述】:

问题 1:

   var _curry1 = function _curry1(fn) {
        return function f1(a) {
            if (arguments.length === 0) {
                return f1;
            } else if (a != null && a['@@functional/placeholder'] === true) {
                return f1;
            } else {
                return fn.apply(this, arguments);
            }
        };
    };

检查a['@@functional/placeholder'] === true的目的是什么?

问题 2:

http://ramdajs.com/0.18.0/docs/#reduce

如何阅读符号?

(a,b -> a) -> a -> [b] -> a

这是我第一次看到这样的符号,它来自哪里?

【问题讨论】:

    标签: javascript functional-programming ramda.js


    【解决方案1】:

    问题 1:

    没有“符号”。 __.js 应该清除它:

    module.exports = {'@@functional/placeholder': true};
    

    所以@@functional/placeholderfoo 没有什么不同

    a = { foo: true }
    a.foo
    a["foo"]
    

    (很明显,你不能写a.@@functional/placeholder,因为那里有很多奇数符号。)

    在该文件中也可以看到意图:

    /**
     * A special placeholder value used to specify "gaps" within curried functions,
     * allowing partial application of any combination of arguments,
     * regardless of their positions.
     *
     * If `g` is a curried ternary function and `_` is `R.__`, the following are equivalent:
     *
     *   - `g(1, 2, 3)`
     *   - `g(_, 2, 3)(1)`
     *   - `g(_, _, 3)(1)(2)`
     *   - `g(_, _, 3)(1, 2)`
     *   - `g(_, 2, _)(1, 3)`
     *   - `g(_, 2)(1)(3)`
     *   - `g(_, 2)(1, 3)`
     *   - `g(_, 2)(_, 3)(1)`
     ...
    

    所以目的是能够在柯里化时“跳过”一些地方。测试决定参数是真实参数还是__.js 占位符,并据此执行。为什么是@@functional/placeholder——大概是因为希望它太诡异,不会与任何人的合法数据发生冲突。

    问题 2:

    符号是类型论中的标准,并由 Haskell 推广。 ab 是任何类型。 (...) 是一个类型的元组,[a] 是一个列表,其元素是 aa -> b 是一个函数,它接受 a 类型的参数并产生 b 类型的返回,并且是右关联的。有问题的示例如下:

    它是一个接受参数的函数,一个接受两个参数(分别为ab 类型)并返回a 类型值的函数;并生成一个函数,该函数接受a 类型的参数,并返回一个函数,该函数接受一个参数为b 类型的元素列表,返回一个a 类型的值。

    这读起来很容易混淆,但不带柯里式的描述会更容易一些:它是一个接受三个参数的函数:第一个是函数(如上所述),第二个是 a 的值,第三个是b 元素的列表,返回值a

    具体来说R.reduce就是这样一个函数:在

    R.reduce(add, 10, numbers);
    

    add是一个函数,它接受两个整数(ab都一样,整数),并返回一个整数((a, b) -> a); 10 是整数类型 (a); numbers 是整数列表 ([b]);并且返回值是一个整数(a)。

    请注意,它混合了 curried 和 uncurried 语法;如果是完全咖喱,add 将是 a -> b -> a,而不是 (a, b) -> a

    【讨论】:

    • “为什么是@@functional/placeholder - 大概正是因为希望它太怪异,因此不会与任何人的合法数据发生冲突。”那并且有希望其他库可能决定使用相同的令牌并且可以就占位符进行互操作。这似乎比使用特定于 Ramda 的东西要好。
    【解决方案2】:

    问题 2:

    这是一个 Hindley-Milner 类型的签名。对于给出的示例,“a”和“b”是任意类型,“->”是一个函数。

    让我们分解一下吧。

    首先,我们采用类型 'a' 和函数 'b -> a'

    (a, b -> a)

    这返回一个函数,它返回一个函数,..(因为你知道,currying)。关键是我们可以添加 '()' 使其更具可读性。

    (a, b -> a) -> (a -> ([b] -> a))

    所以如果你传递这个函数 'a' 和一个函数 'a' -> 'b',你就会回来

    a -> ([b] -> a)

    如果你传递这个类型'a'

    [b] -> 一个

    其中 [b] 是一个类型为 'b' 的数组。传递这个函数 [b] 给你 一种a

    一个

    如果你想了解更多关于 JavaScript 函数式编程的内容,我可以推荐The Mostly Adequate Guide

    【讨论】:

    • 不是你的错,我不得不改变我的答案,但由于(我认为)草率,a,b -> a 的意思是(a, b) -> a,而不是人们期望的(a, (b -> a))。该签名页面上给出的示例是var add = (a, b) => a + b;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 2018-04-01
    相关资源
    最近更新 更多