嵌套的纯函数还是纯函数吗?

Is a nested pure function still a pure function?

根据定义,如果满足以下条件,纯函数 是纯函数:

所以这是一个纯函数:

function foo(x) {
  return x * 2;
}

foo(1) // 2
foo(2) // 4
foo(3) // 6

这也是一个纯函数(在 JavaScript 上下文中)

Math.floor(x);

Math.floor(1.1); // 1
Math.floor(1.2); // 1
Math.floor(2.2); // 2

问题:如果我们将这两个纯函数组合起来,它是否仍被视为纯函数?

// Nested with Math library
function bar(x) {
  return Math.floor(x);
}

// Nested even deeper
function foobar(x) {
  return foo(Math.floor(x));
}

显然,它仍然总是 return 在没有副作用的情况下给定相同的输入相同的输出,但是从其他上下文(范围)调用函数确实违反了“依赖于不外部状态"?

外部状态不同于外部代码。如果纯函数不能使用外部代码,那么几乎就没有纯函数这样的东西了。即使你的函数所做的只是 x * 2,在(许多)纯函数式语言中甚至 * 也是一个函数 。所以即使是这个简单的函数也无法避免调用其他函数。

函数定义或多或少只是语法细节。您可以将外部函数的函数体内联到更长的表达式中。例如:

function foo(a, b) {
    return bar(a) + bar(b);
}

function bar(x) {
    return x * 2;
}

等同于:

function foo(a, b) {
    return a * 2 + b * 2;
}

唯一的区别是代码片段的可重用性 and/or 可读性和可维护性。不是纯度。

如果一个函数不引起副作用或受其自身之外的 effects/state 影响,那么它就是纯函数。只要它调用的所有代码也符合该规则,它就会保持纯净。

Does calling a function from other context (scope) break the law for "Relies on no external state"?

如果 argumentsreturn value 之间的 link 仍然是纯的,则不会。

纯函数将输入 (arguments) 映射到输出 (return value),其方式仅基于 arguments 和除了生成 return value 所需的代码外,不包含任何其他代码。

如何测试一个函数是否纯

您可以应用这个简单的测试来确定它是否纯净:

function multiplication (integer) {

var result = 2 * integer;
return result;
}

console.log(multiplication(4)) // 8

关于 multiplication(integer) 永远正确的是,您在代码中可以简单地用它为给定 argument 生成的 return value 替换对它的调用。也就是说,您可以只写 8 而不是在您的代码中编写 multiplication(4)。一旦函数变得不纯,此测试就会失败:

function multiplicationImpure (integer) {

    var result = 2 * integer;
    console.log (result);
    return result;
    }

console.log(multiplicationImpure(4)) // 8 8

现在,如果您在代码中将 multiplicationImpure(4) 替换为 8,它将不再相同:控制台的输出中将缺少一个 8。同样,如果某些外部状态可能导致另一个 return 值而不是 8 参数 2 .

我认为,在 JavaScript、

function foo(x) {
  return Math.floor(x);
}

不是纯函数。如果 Math 只是一个名称空间,我会同意。但在 JavaScript (AFAIK) 中,它是一个功能齐全的可变对象。因此 foo 依赖于外部 Math 对象的状态而不是纯粹的。使其纯净的一种方法是使用

const floor = Math.floor;
function foo(x) {
  return floor(x);
}

这样,foo 将不依赖于 Math 对象的状态,并且是纯粹的。