嵌套的纯函数还是纯函数吗?
Is a nested pure function still a pure function?
根据定义,如果满足以下条件,纯函数 是纯函数:
- 给定相同的输入,将始终return相同的输出。
- 没有副作用。
- 不依赖外部状态。
所以这是一个纯函数:
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"?
如果 arguments
和 return 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
对象的状态,并且是纯粹的。
根据定义,如果满足以下条件,纯函数 是纯函数:
- 给定相同的输入,将始终return相同的输出。
- 没有副作用。
- 不依赖外部状态。
所以这是一个纯函数:
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"?
如果 arguments
和 return 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
对象的状态,并且是纯粹的。