为什么不认为这种纯函数的实现具有外部依赖性?
Why this implementation of a pure function isn't considered to have external dependencies?
我对 pure function
的概念很满意,比如非常简单的例子...
function addTwo(val){
return val + 2;
}
给定相同的参数,它会产生相同的结果,从而导致 Referential Transparency 和良好的确定性代码。
但后来我遇到了这样的例子(取自 professor frisby mostly adequate guide,但我在其他 FP JS 书籍中找到了类似的例子)
//pure
var signUp = function(Db, Email, attrs) {
return function() {
var user = saveUser(Db, attrs);
welcomeUser(Email, user);
};
};
var saveUser = function(Db, attrs) {
...
};
var welcomeUser = function(Email, user) {
...
};
我不明白为什么不将对 saveUser
或 welcomeUser
.
的调用视为外部依赖(因此,不纯)
我知道从 function/IO 的角度来看,signUp
总是 return "same"(等效的)连线函数,但我觉得很奇怪。
我很难理解为什么
function multiplyBy(times){
return value => value * times;
}
const fiveTimes = multiplyBy(5);
fiveTimes(10);
被认为是 pure
。从 returned 函数 POV,访问 times
是对作用域链的查找,它可能来自直接外部作用域,也可能来自外部作用域(如全局作用域)。
有人想对此有所启发吗?
纯函数的定义是:
A function that does always evaluates the same result value given the same argument value(s) and that does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.
"Having dependencies" 在定义纯函数中完全没有作用。唯一重要的是函数是否有任何 副作用 以及它的结果是否取决于 外部状态 。如果一个函数的行为完全相同,并且在给定相同输入的情况下总是产生相同的结果,那么它就是纯函数。如果函数有任何副作用(修改全局状态)或根据外部状态表现不同,则它是不纯的。一个函数可能依赖于(阅读:call)另一个函数作为其操作的一部分;只要其他功能也是纯的,就不会污染纯度。
您展示的 signUp
示例是纯粹的,因为它仅作用于其输入,并且在使用相同输入调用时始终 return 输出完全相同的输出。请注意,函数本身没有 "do" 任何东西。它不会调用数据库或产生任何副作用。它所做的只是 return 一个函数。但是如果输入相同,这个 returned 函数总是相同的。 returned 函数实际上是不纯的;但产生它的函数不是。
我对 JavaScript 中函数纯度的解释是,不存在二进制 "pure" 或 "impure" 这样的东西,而是一个函数行为可预测的置信度范围。例如,通过传递一个带有副作用 getter 的对象,可以使用各种技巧来制作一个看似纯粹的函数。
所以,一旦我们意识到纯度与置信度有关,我们就可以问,我对某些函数会按我预期的方式运行有多大信心?如果该函数引用另一个函数,您如何确定另一个函数是纯函数?而且,此外,您如何确定引用该其他函数的标识符不会/不能重新分配以指向您不知道的其他一些函数?
我个人编写我的程序,所以我几乎从不重新定义指向函数的标识符,尤其是在声明该函数而不仅仅是函数表达式的情况下。通过这种方式,我非常有信心(比如说,99.99%)如果 foo(..)
调用 bar(..)
,并且我相信 bar(..)
是可靠的,那么 foo(..)
是也很可靠,因为我知道我不会将 bar(..)
重新分配给任何其他函数并导致令人惊讶的结果。
有些人甚至用 const fn = function ..
来定义他们的函数标识符。我不认为这有多大帮助……它可能会使我的信心水平从 99.99% 提高到 99.999%。在我看来,这并不足以证明它的使用是合理的。
此外,关于你问题的闭包部分:如果一个内部函数关闭了一个仍然包含在纯函数中的外部变量,并且没有任何东西重新分配该变量,那么它 有效 一个常数,所以我对可预测性的信心水平非常高。
但再次强调,JS 中的函数纯度与置信度有关,而不是绝对的二元是或否。
我对 pure function
的概念很满意,比如非常简单的例子...
function addTwo(val){
return val + 2;
}
给定相同的参数,它会产生相同的结果,从而导致 Referential Transparency 和良好的确定性代码。
但后来我遇到了这样的例子(取自 professor frisby mostly adequate guide,但我在其他 FP JS 书籍中找到了类似的例子)
//pure
var signUp = function(Db, Email, attrs) {
return function() {
var user = saveUser(Db, attrs);
welcomeUser(Email, user);
};
};
var saveUser = function(Db, attrs) {
...
};
var welcomeUser = function(Email, user) {
...
};
我不明白为什么不将对 saveUser
或 welcomeUser
.
我知道从 function/IO 的角度来看,signUp
总是 return "same"(等效的)连线函数,但我觉得很奇怪。
我很难理解为什么
function multiplyBy(times){
return value => value * times;
}
const fiveTimes = multiplyBy(5);
fiveTimes(10);
被认为是 pure
。从 returned 函数 POV,访问 times
是对作用域链的查找,它可能来自直接外部作用域,也可能来自外部作用域(如全局作用域)。
有人想对此有所启发吗?
纯函数的定义是:
A function that does always evaluates the same result value given the same argument value(s) and that does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.
"Having dependencies" 在定义纯函数中完全没有作用。唯一重要的是函数是否有任何 副作用 以及它的结果是否取决于 外部状态 。如果一个函数的行为完全相同,并且在给定相同输入的情况下总是产生相同的结果,那么它就是纯函数。如果函数有任何副作用(修改全局状态)或根据外部状态表现不同,则它是不纯的。一个函数可能依赖于(阅读:call)另一个函数作为其操作的一部分;只要其他功能也是纯的,就不会污染纯度。
您展示的 signUp
示例是纯粹的,因为它仅作用于其输入,并且在使用相同输入调用时始终 return 输出完全相同的输出。请注意,函数本身没有 "do" 任何东西。它不会调用数据库或产生任何副作用。它所做的只是 return 一个函数。但是如果输入相同,这个 returned 函数总是相同的。 returned 函数实际上是不纯的;但产生它的函数不是。
我对 JavaScript 中函数纯度的解释是,不存在二进制 "pure" 或 "impure" 这样的东西,而是一个函数行为可预测的置信度范围。例如,通过传递一个带有副作用 getter 的对象,可以使用各种技巧来制作一个看似纯粹的函数。
所以,一旦我们意识到纯度与置信度有关,我们就可以问,我对某些函数会按我预期的方式运行有多大信心?如果该函数引用另一个函数,您如何确定另一个函数是纯函数?而且,此外,您如何确定引用该其他函数的标识符不会/不能重新分配以指向您不知道的其他一些函数?
我个人编写我的程序,所以我几乎从不重新定义指向函数的标识符,尤其是在声明该函数而不仅仅是函数表达式的情况下。通过这种方式,我非常有信心(比如说,99.99%)如果 foo(..)
调用 bar(..)
,并且我相信 bar(..)
是可靠的,那么 foo(..)
是也很可靠,因为我知道我不会将 bar(..)
重新分配给任何其他函数并导致令人惊讶的结果。
有些人甚至用 const fn = function ..
来定义他们的函数标识符。我不认为这有多大帮助……它可能会使我的信心水平从 99.99% 提高到 99.999%。在我看来,这并不足以证明它的使用是合理的。
此外,关于你问题的闭包部分:如果一个内部函数关闭了一个仍然包含在纯函数中的外部变量,并且没有任何东西重新分配该变量,那么它 有效 一个常数,所以我对可预测性的信心水平非常高。
但再次强调,JS 中的函数纯度与置信度有关,而不是绝对的二元是或否。