纯函数能否存在于纯面向对象编程语言中?

4
对于这个问题,我所说的“纯面向对象编程语言”是指函数只能存在于(静态或非静态)对象内部,即作为方法。
考虑以下Java代码:
import java.lang.Math;

class Program {

     public static void main(string[] args){
          Math.addExact(2, 3);
          new Addends(2, 3).sum();
     }
}

final class Addends {
     private final int addend1;
     private final int addend2;
     Addends(int x, int y){
        addend1 = x;
        addend2 = y;
     }

     final int sum(){
        return addend1 + addend2;
     }
}

在这个例子中:
1. Math.addExact 是一个纯函数吗? 2. Addends.sum 是一个纯函数吗?
第一个问题的答案取决于如何理解方法与函数的关系,即方法是否被认为是函数的一种类型或仅仅是它们最接近的面向对象编程(OOP)等效物。
第二个问题的答案取决于将值注入到对象中的字段是否可以被视为使用这些字段的相关方法的输入(假设纯函数是对于相同的输入给出相同输出的函数)。认为如此的原因是承认对于任何对象,特别是那些表现出高内聚性的对象,将其内部的任何n参数方法转换为一个n-m参数方法都是相当容易的,只需通过将m个值注入到m个不可变字段中,并将这些字段分配给该对象的m参数构造函数即可。
注意:我认识到这个问题的答案很大程度上是语义/约定的问题。我想知道是否有关于这个问题达成的共识,如果有的话,是什么。

问题被关闭为基于观点的澄清:如上所述,我并不是要求个别贡献者对这个问题发表意见:我想知道程序员和/或计算机科学家是否在像给出的那些例子中达成了一致,基于a)方法是否被认为是函数,以及b)在纯函数的定义中“输入”被广泛解释的方式; 如果有收敛,那就是什么。比较

  • 基于观点:道德是什么?
  • 非基于观点:维基百科上如何定义道德?
  • 有争议的:不可数集是否存在?
  • 无争议的:在古典集合论中是否可以证明不可数集的存在(是)? 直觉主义集合论呢(否)?

1
我不知道问题是什么。是的,两者都是方法。是的,两者都与类相关联。其中一个是类方法,另一个是实例方法。 - akuzminykh
1
也许您还可以查看以下内容:方法和函数有什么区别?方法 vs 函数 vs 过程 - akuzminykh
你如何定义“纯函数”?我认为回答这个问题需要了解这个概念。 - NomadMaker
@JacobArchambault,meriton的回答是否符合您的期望,还是您的问题仍然不同? - akuzminykh
另一方面,答案的第二部分真的很有趣,让我有很多东西可以思考。 - Jacob Archambault
显示剩余4条评论
1个回答

0
在数学中,函数是一个映射,将输入映射到输出,以便每个输入都映射到唯一的输出。
当计算机科学人员谈论“纯函数”时,他们指的是可以像数学函数一样处理的东西。
这几乎就是所有人都同意的。你看,我们能否将某物“像数学函数一样处理”取决于我们感兴趣的内容。它还取决于我们将计算机代码如何转换为数学领域。
为什么我们的兴趣很重要
方法
int foo(x) {
    logger.trace("foo was called with {}, x);
    return x * x;
}

如果我们不关心日志记录,那么这是纯的,但如果我们关心,则是不纯的。

这个方法

int max(int x, int y, int z) {
    return IntStream.of(x, y, z).max().get();
}

如果我们不关心对象分配,或者IntStream类将被初始化,则它是纯的,但如果我们关心,则是不纯的。

为什么数学翻译很重要

在处理面向对象编程语言时,显然存在一个挑战,即方法附加到对象上,但数学函数并没有。我们可以用两种方式来处理:

  • 我们可以假装函数不受其所附着的对象的影响。也就是说,给定一个方法

    int f(int x) {
        return x + 1
    }
    

    我们将其视为函数

    f(x) = x + 1
    

    对于许多目的来说,这可能完全足够。

  • 或者,我们可以将this和通过它可达的状态视为隐式参数传递给我们的函数。例如,如果我们有

    int f(int x) {
        return x + this.x;
    }
    

    我们将其视为函数

    f(heap, this, x) = x + heap(this)("x")
    

    其中heap是一个接受对象引用并返回一个接受字段名并返回该对象当前具有的值的函数。

这两种方法都有用,但哪一种更好取决于你想要什么。这就是为什么当有人谈论纯函数时,你应该问他们使用的是哪个定义。


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