从另一个函数获取值的函数是否被视为纯函数?


9

我试图找出一种在没有副作用的情况下处理默认变量值的方法,并且最终得到以下结果:

function getDefaultSeparator() {
    return ':';
}

function process(input, separator) {
    var separator = separator || getDefaultSeparator();

    // Use separator in some logic

    return output;
}

默认分隔符将在其他函数中使用,我只想在一个地方定义它。

如果这是一个纯函数,那么与仅使用全局DEFAULT_SEPARATOR常量有什么区别?


5
除非您打算将该函数用作占位符,以便稍后添加一些逻辑,否则没有实质性区别。
罗伯特·哈维

3
可能的重复是一个函数立即不纯的,如果它需要一个函数作为参数?。问题并非完全相同,但答案应该相同。(“这取决于其他函数的纯度。”)
jpmc26,2016年

1
使用全局常量不会使函数不纯。使用假定为常量的全局值确实可以。
chepner

顺便说一句,您可以咖喱process(带有相反的参数顺序),而不是专门使用咖喱函数来var processDefault = process(":")
bob

Answers:


22

从另一个函数获取值的函数是否被视为纯函数?

这取决于其他函数的功能以及调用函数的功能。杂质具有传染性,纯度不是。

调用纯函数不会改变调用函数的纯度。调用不纯函数会自动使调用函数也不纯。

因此,在您的示例中,它取决于您遗漏的部分的纯度:如果那是纯净的,那么整个功能就是纯净的。

如果这是一个纯函数,那么与仅使用全局DEFAULT_SEPARATOR常量有什么区别?

没有。始终返回相同值的函数与常数是无法区分的。实际上,这就是在λ微积分中建模常量的方式。


2
“自动调用不纯函数也会使调用函数不纯”。您确定吗?AFAICS,调用不纯函数虽然会这样做,但不会自动使调用者不纯。
重复数据删除器

2
@Deduplicator:取决于您可以(烦恼)执行多少静态分析。当然,如果有一个函数func在传递0时有副作用,但是在传递1时没有副作用,则可以合理地说,尽管func它本身是“不纯的”,但调用它的函数为func(1)(并忽略返回值,让我们说)不一定是不纯的。调用func足以“污染”调用者潜在的不纯,但受污染的函数可能以某种方式被证明是纯净的。至少在javascript中,语言中未定义纯/不纯。
史蒂夫·杰索普

6

是的,它们都是纯函数(假设省略的部分也是纯函数),因为:

  1. 结果仅取决于参数。
  2. 没有副作用。

注意,如果getDefaultSeparator()不是纯函数,那么两个函数都不是纯函数process()

在Javascript中,使用纯函数或常量之间没有有意义的区别,只要避免使用Javascript重新定义函数或更改常量值的能力,纯函数都可以使用它们。

纯函数背后的一个关键概念是,可以用返回的值替换它们,而不会影响程序的结果。


1

正如其他人说的那样,当然,它仍然是一个纯函数。

但是,让我们谈谈设计问题。您可以尝试通过将值仅放置一次来做一些事情来保持代码DRY。另外,我认为还应该考虑的是适当的耦合级别。

使用函数为您提供了更大的灵活性来更改实现,也就是说,函数方法比全局变量提供了更宽松的耦合。

问题是是否需要?

如果使用者和提供者在同一个模块中,并且提供者是该模块的私有成员,则很难争辩这种松散耦合的级别是必要的,因为如果提供者需要从私有变量升级到私有变量,则事实是如此。私有方法,模块内的简单重构可以同时应用于使用者。在您真正需要之前使用方法/功能可能属于YAGNI。

即使使用者和提供者位于不同的模块中,但这些模块一起版本化(例如,您使用的是缩小器,因此使用者和提供者的模块位于同一文件中),YAGNI也可能适用。

另一方面,例如,如果生产者位于与消费者分开版本的库或API包或模块中,则使用该功能可能是合适的。在这种情况下,我们应该考虑API的寿命以及OCP之类的原理。

(另一方面,如果您的代码很大,我鼓励使用带有字段和方法的模块,而不是全局变量和函数。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.