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 - m的对象,通过要求其封闭对象通过注入值来实例化,将其中的任何 n 参数方法转换为参数方法是相当容易的m,分配给m不可变字段,放入m该对象的 -parameter 构造函数中。

注意:我认识到这个问题的答案将部分是语义/约定的问题。我在问是否碰巧就这个问题达成了约定,如果有,它们是什么。

基于意见的问题结束后的澄清:如上所述,我不是在询问个人贡献者对这个问题的意见:我是在询问程序员和/或计算机科学家之间是否存在类似给出的示例,基于 a) 方法是否被视为函数,以及 b) 在纯函数的定义中如何广泛地解释“输入”;如果有收敛,它是什么。相比

  • 基于意见:什么是道德?
  • 不基于意见:维基百科如何定义道德?
  • 争议:存在不可数集吗?
  • 没有争议:在经典集合论中是否可以证明不可数集合的存在(是)?直觉主义集合论(否)呢?
4

1 回答 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")
    

    whereheap是一个函数,它接受一个对象引用,并返回一个函数,该函数接受一个字段名称并返回该字段当前对该对象具有的值。

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

于 2021-02-07T01:13:28.370 回答