嵌套的纯函数仍然是纯函数吗?

时间:2016-10-27 09:29:46

标签: javascript functional-programming immutability

根据定义, 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));
}

显然,在没有副作用的情况下,它仍然总是返回相同的输出相同的输出,但是从其他上下文(范围)调用函数会违反法律#34; 依赖于无外部状态"

3 个答案:

答案 0 :(得分:9)

外部状态外部代码不同。如果纯函数不能使用外部代码,那么根本就没有纯粹的函数。即使你的所有函数都是x * 2,在(很多)纯函数式语言中,即使* 也是一个函数。所以即使是这个简单的函数也无法避免调用其他函数。

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

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

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

与:

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

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

如果功能不会引起副作用或受到自身外部副作用/状态的影响,则该功能是纯粹的。只要它调用的所有代码也符合该规则,它就会保持纯粹。

答案 1 :(得分:1)

  

从其他上下文(范围)调用函数是否违反了法律   “不依赖外部状态”?

argumentsreturn value之间的链接仍然是纯粹的。

纯函数将输入(arguments)映射到输出(return value),其方式可以仅基于arguments以100%的准确度进行预测,并且不包含生成return value所需的任何其他代码。

如何测试函数是否纯粹

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

function multiplication (integer) {

var result = 2 * integer;
return result;
}

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

multiplication(integer)的真实情况是,您的代码中的代码可以简单地用它为给定return value生成的argument替换对它的调用。这不是在您的代码中编写multiplication(4),而是可以编写8。一旦函数变得不纯,该测试就会失败:

function multiplicationImpure (integer) {

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

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

现在,如果您在代码中将multiplicationImpure(4)替换为8,则它将不再相同:在控制台的输出中将丢失一个8。同样,如果某个外部状态可能导致参数8的另一个返回值超过8,那么简单地将2放入代码就会出现问题。

答案 2 :(得分:0)

我认为,在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对象的状态而且是纯粹的。