0

I'm studying functional programming and I just read about Pure functions.

My question is: A pure function can change its parameters?

Is this function pure?

int a(Payment payment){
 payment.setValue(payment.getValue() - 1);
 return payment.getValue() * 10;
}

2 Answers2

3

Two things here:

  1. A pure function is a function with return value based only on its input arguments, and calling the function has no side effects.

  2. The piece of Kotlin code you pasted doesn't compile (see https://ideone.com/fli05T). The compiler says val cannot be reassigned. It's because in Kotlin, function arguments are immutable.

In theory, if it was possible to define such function as you wrote, then by definition from (1), it would be pure, assuming that the parameters are passed by value (changing them inside the function doesn't change them as seen from outside the function).

PiotrK
  • 1,502
  • 1
  • 15
  • 33
  • Sorry about that, I changed to Java code and change the parameter to an object, not a primitive value. So now, the function `a()` is pure? – Mário Sérgio Esteves Alvial Aug 21 '18 at 21:03
  • 2
    No because it has a side-effect - it mutates its parameter by setting the value of the payment. – PiotrK Aug 21 '18 at 21:03
  • @PiotrK that would be an assumption. `setValue` might return a new `Payment` and the example should then always return 10 times the argument. – Sylwester Aug 22 '18 at 20:49
  • 1
    @Sylwester true, it's the assumption, but it's safer to assume that we don't know the implementation of `setValue`. Especially because there's a convention in Java Beans (if I'm not mistaken) and generally in Java that `setXXX` means a setter. Setter is a kind of mutator, and the name "mutator" speaks for itself. – PiotrK Aug 23 '18 at 19:19
2

The rule is no side effects. Mutating an object is a side effect. However it doesn't really say that you are mutating so here is a version of Payment where your code is pure:

public class Payment
{
  private int value;

  public Payment(int value) {
    this.value = value;
  }
  public Payment setValue(int value) {
    return new Payment(value);
  }
  public int getValue() {
    return value;
  }

  public static int a(Payment payment) {
      payment.setValue(payment.getValue() - 1); // dead code
      return payment.getValue() * 10;
  }

  public static int b(Payment payment) {
      return payment
        .setValue(payment.getValue() - 1)
        .getValue() * 10;
  }

  public static void main(String args[]) {
      Payment p = new Payment(10);
      System.out.println(String.valueOf(a(p)));
      System.out.println(String.valueOf(b(p)));
  }
}

Notice the definition of your a isn't changed and it is 100% functional. If you pass it 10 it returns 100, always 10 times the input. However the first line that returns a new Payment with the value 9 is never used so it is dead code. The intent was perhaps that of my rewritten version, b. b is also functional.

Now other implementations of Payment might make a and b impure.

Many people think OO and functional doesn't mix. One of the oldest and most commonly used class in Java, java.lang.String, is both object oriented and a purely functional interface. No method mutates, only return a new object.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • 1
    I'd be careful calling it a [functional interface](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) since that has an actual meaning in Java and [java.util.String is a public final class](https://docs.oracle.com/javase/10/docs/api/java/lang/String.html)... or is this wrong? – Water Aug 21 '18 at 22:32
  • 1
    @Water From the link you provided: "Strings are constant; their values cannot be changed after they are created.". Thus the class String provides a 100% functional interface, meaning you won't have any detectable side effects. It is different form purely functional which needs to peek into what `toLowerCase` actually does and see if it mutates, but from the interface standpoint it is functional since you get a new string from the old. I have no idea what Java has coocked into the term functional interface but it seems like the command pattern. – Sylwester Aug 22 '18 at 00:44