纯函数能够调用外部函数吗?

12

一个纯函数可以调用外部方法吗?

例如:

class Dog {
  function jump(name) {
    return "a dog named " + name + " jumped!"
  }

  function jumpTwice(names) {
    var result = [];
    for (var i = 0; i < 2; i++) {
       result.push(jump(names[i]));
    }
    return result.join("\n");
  }

}

跳两次(jumpTwice())可以被视为一个纯函数(pure function)吗?

3个回答

21

当可以时

一个纯函数f可以调用任何其他函数/方法g0...gn。 但是,g0...gn 也必须是纯的

当不可以时

一旦您从f中调用一个非纯的函数g,那么f就不再是纯函数了。


但是jumpTwice取决于jump的行为。如果jump的定义发生变化,那么jumpTwice的行为也会发生变化。这难道不违反了纯函数的“相同输入,相同输出”的规则吗? - Marc de la Barrera i Bardalet
1
纯函数不应该保证在更改代码库并重新构建项目后输出相同的结果。 - Luca Angeletti
1
纯函数在更改代码库和重新构建项目后不应保证相同的输出。 - undefined

0

是的,它是纯净的。它不会改变任何全局状态,也不会针对相同的输入给出不同的结果。


0
在你提供的特定情况下,是的。但你所拥有的是一个方法,而方法需要额外的注意。
纯函数始终为任何给定的输入提供相同的结果,无论当前程序状态如何。方法可以被视为将其对象作为隐藏参数传递的函数。为了保持纯净,该方法不能访问任何隐含状态(也不能调用任何其他易受隐含状态影响的方法/函数)。这也意味着不使用包含隐含状态的任何对象字段。评论讨论希望能够给出如何判断上下文的示例。
仅避免可变字段是不够的 - 不可变字段中的值必须是可知/可预测的。例如,如果一个对象包含一个不可变的私有字段,在对象创建时赋予一个随机数,则使用该值计算其输出的任何方法都是不纯的。
另一方面,如果您的Dog类具有一个不可变的名称字段,在对象创建时设置该字段,则使用该字段的方法可以被认为是纯的(除非其他原因使它们不合格)。
编辑
“副作用”和“纯净性”是有环境上下文的(正如评论中讨论的那样),如果能说明这一点将非常有帮助。这也是我在使用“可知”和“可预测”这些词语时没有完全清晰地暗示出来的地方。评论讨论展示了理解上下文的重要性。”

我不确定你所说的“可知/可预测”的意思。对象中的所有字段都会对该方法的输入产生影响。对象的创建虽然是不纯的(涉及随机性),但这并不会使方法本身变得不纯。 - Bergi
如果该方法忽略对象的有状态属性,则它是可预测和纯净的。在这种情况下,无论输入的可变部分如何,输出都是可预测的。 - itsbruce
1
不,使用带有隐藏随机字段的对象并不是纯粹的,只有在对象上调用返回隐藏字段的方法才是。而且,它们一起显然是不纯的。 - Bergi
1
是的,如果你对上下文非常准确,那么我会认同你的观点。 - itsbruce
1
作为一个功能性面向对象的好例子,我倾向于指向Java中的String类。所有的方法都是纯的,实例从不改变其状态。 - Sylwester
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接