纯函数与Java

纯函数与Java,java,lambda,functional-programming,Java,Lambda,Functional Programming,我对Java和纯函数有一些疑问。据我所知,纯函数是一个包含以下两条语句的函数: 没有副作用 相同的输入得到相同的结果 根据这一点(作为一个例子),此函数将是纯函数: int sum(int a, int b) { return a + b; } 但是,这个函数会被认为是纯函数吗? int sum(Person a, Person b) { return a.getAge() + b.getAge(); } // Correct int[] f = new int[]{ 0 }; IntStr

我对Java和纯函数有一些疑问。据我所知,纯函数是一个包含以下两条语句的函数:

  • 没有副作用
  • 相同的输入得到相同的结果
  • 根据这一点(作为一个例子),此函数将是纯函数:

    int sum(int a, int b) { return a + b; }
    
    但是,这个函数会被认为是纯函数吗?

    int sum(Person a, Person b) { return a.getAge() + b.getAge(); }
    
    // Correct
    int[] f = new int[]{ 0 };
    IntStream.of(1,2,3).map(e -> e * f[0]).forEach(System.out::println);
    f[0] = 25;
    

    我的猜测是否定的,因为根据作为参数传递给函数的Person对象,结果会有所不同

    考虑到Java中的对象(以及一般的OO语言)具有隐藏信息,任何包含对象作为参数的函数都可以被认为是纯函数吗?

    int sum(Person a, Person b) { return a.getAge() + b.getAge(); }
    
    // Correct
    int[] f = new int[]{ 0 };
    IntStream.of(1,2,3).map(e -> e * f[0]).forEach(System.out::println);
    f[0] = 25;
    
    另一个问题,如果一种语言/程序的任何功能都不是纯的,它能被认为是纯的吗?

    int sum(Person a, Person b) { return a.getAge() + b.getAge(); }
    
    // Correct
    int[] f = new int[]{ 0 };
    IntStream.of(1,2,3).map(e -> e * f[0]).forEach(System.out::println);
    f[0] = 25;
    
    考虑到所有这些,一个Java程序(相当复杂)是否只能由纯函数(可以说是纯函数)组成,还是仅仅是不可能的事情?

    int sum(Person a, Person b) { return a.getAge() + b.getAge(); }
    
    // Correct
    int[] f = new int[]{ 0 };
    IntStream.of(1,2,3).map(e -> e * f[0]).forEach(System.out::println);
    f[0] = 25;
    
    另一个问题是,就编译器而言,lambda表达式只能使用final(或实际上是final)变量:

    // Correct
    int f = 0;
    IntStream.of(1,2,3).map(e -> e * f).forEach(System.out::println);
    
    // Compilation error
    int g = 0;
    IntStream.of(1,2,3).map(e -> e * g).forEach(System.out::println);
    g = 22;
    
    在这种情况下,该代码如何编译?

    int sum(Person a, Person b) { return a.getAge() + b.getAge(); }
    
    // Correct
    int[] f = new int[]{ 0 };
    IntStream.of(1,2,3).map(e -> e * f[0]).forEach(System.out::println);
    f[0] = 25;
    
    任何涉及对象作为参数的函数都可以被认为是纯函数吗

    是,如果参数是不可变的


    我的猜测是否定的,因为根据作为参数传递给函数的Person对象,结果会有所不同

    这不是正确的理由。但同一个物体在不同的时间点可能有不同的年龄

    如果一种语言/程序的任何功能都不是纯的,它能被认为是纯的吗

    我不确定,但我的回答是否定的,因为
    pure
    的含义被这个不纯函数所否定

    这段代码怎么可能编译成这种情况


    因为引用是最终的。

    “因为结果因作为参数传递给函数的Person对象而异”-嗯,那么?接受整数的函数的结果因传递的整数而异。大多数纯函数如果给它们不同的输入,则会给出不同的输出。
    因为结果因传递的Person对象而异
    -第一个函数的结果也因传递的int参数而异。对我来说,这是一个纯函数,如果它修改了一些物体的内部场,它就不会是纯函数。这是五个问题。你真的应该把他们当作五个独立的问题来问。@backslax,除非
    Person
    中有
    setAge
    方法。如果有,您可以将相同的两个
    Person
    对象传递给
    sum
    ,第二次得到不同的结果。
    相同的对象在不同的时间点可以有不同的年龄。
    没错,但您依赖于两个
    int
    字段:对于每个
    int
    对,您得到一个且只有一个输出,使函数的输出一致。也许我遗漏了一些东西,但我认为这不会使函数变得不纯。不变性在这里有什么关系?想象一个例子,当一个不可变类
    Person
    实现
    getAge()
    作为一个有副作用的方法时——比如,在返回年龄之前打印年龄。这将使我们的
    总和
    不纯,即使
    是不变的。我认为这里需要比不变性更强的东西。@反斜杠见问题的第二点。您可以说无论调用
    sum
    后对象发生什么情况,
    sum
    始终返回相同的值吗。如果答案是否定的,那就意味着函数是不纯的。@dasblinkenlight
    这会使我们的和变得不纯,即使Person是不可变的
    我不明白。无论何时调用该方法,它都将以相同的方式运行。如果打印,它将始终打印相同的值。@偶氮纯函数不能有副作用。印刷是一种副作用。