29

I'm working through a textbook at the moment which defines a pure method as:

"a static method that depends only on its parameters and no other data"

Would it not be possible to have an instance method be a pure method without it being static (as long as it doesn't modify parameters and doesn't have 'side-effects' like printing)?

I know for a pure method to be the pure, the return value only depends on the parameters and not on any other state, so perhaps the way instance methods are called means that the variables taken from the object calling the method don't count as parameters but as another "state"?

Other than that I can't think of any reason why a non-static method couldn't be a pure method.

Here's an example:

public class Rational {

    private int numer;
    private int denom;

    public Rational() {
        this.numer = 0;
        this.denom = 1;
    }

    public Rational(int numer, int denom) {
        this.numer = numer;
        this.denom = denom;
    }
}

The above defines a Rational class

You could then write a method in the Rational class which returns a Rational object as a double by either 'Method one' or 'Method two' below.

Method one:

public double toDouble() {
    double x = this.numer;
    double y = this.denom;
    double fprat = x / y;
    return fprat;
}   

Method two:

public static double toDouble(Rational rational)
{
    double x = rational.numer;
    double y = rational.denom;
    double fprat = x / y;
    return fprat;
} 

They essentially do exactly the same thing but one is a static method and the other is an instance method so their calls would be in a different format. Method two is certainly a pure method but would Method one, which is non-static, also be defined as a pure method under these circumstances?

9
  • I guess so. If you have a "pure" static method in a Java class, then you can just remove static, and its dependencies, in theory, would not change. Commented May 22, 2018 at 11:14
  • 10
    If you look at it from an architectural point of view, it wouldnt be logic to have a pure method as an instance method. It is pure because it holds no state and is idempotent so it probably should be a static method Commented May 22, 2018 at 11:20
  • 3
    If the method is not static, then you are passing an implicit this parameter. And the requirements for parameters have to hold for that implicit this parameter too. Commented May 22, 2018 at 11:53
  • 2
    Can anyone offer some advice on how I can edit this question to not come across as "primarily opinion based"? I'm trying to ask about the fundamental definitions of common Java terminology, not people's opinions on them. I appreciate all the answers so far and have continued to search for clarification myself. I'm currently reading through the JML section on pure methods and constructors. You can find that here if anyone's interested. eecs.ucf.edu/~leavens/JML/jmlrefman/jmlrefman_7.html#SEC60 Commented May 22, 2018 at 13:52
  • 4
    @Yassin A pure method is absolutely allowed to accept state as an input (otherwise it would be rather pointless). Why should a hidden this pointer be considered any more special than any other parameter to the function? That argument leads to a contradiction: Assume that public static int pureFunc(MyInstance self) is pure, clearly the isomorph public int pureFunc() would be pure as well.
    – Voo
    Commented May 22, 2018 at 15:56

6 Answers 6

29

The "static" part of that definition is superfluous. A method being static doesn't guarantee that it does not rely on any other state. I suspect the definition just wanted to make sure the method does not use instance variables.

On the other hand, technically you may also think of an instance method as a static method with a zero-th parameter, the object itself. If that object is immmutable (or the method does not change anything in the object), you could argue that the method is still pure. Basically you regard the "object" as an additional parameter.

Method references in Java for example can behave this way, making the first argument the object itself on which the method is called.

8
  • 3
    I don't think mutability is relevant in your 2nd paragraph. It should only matter than two equal instances (a==b) produce the same result a.f(x) == b.f(x) (and no side effects)
    – Michael
    Commented May 22, 2018 at 11:32
  • 5
    Could argue? Should argue.
    – Bergi
    Commented May 22, 2018 at 12:53
  • 2
    @RobertBräutigam If you're considering the instance as an implicit argument to the function then if that instances changes between invocations then you are not calling the method with the same arguments as before. Thus, it could still be pure and be mutable.
    – Michael
    Commented May 22, 2018 at 15:24
  • 4
    @Bergi Agreed. I don't see much reason to consider the this parameter passed to an instance any more special than any other argument. Or if the hidden parameter really changes the meaning - why is the hidden class pointer that's passed to static methods not a problem as well? It just doesn't make much sense.
    – Voo
    Commented May 22, 2018 at 15:53
  • 1
    @JoshHardman Do pure methods have to be static? No. If you accept that the object itself ('this' in Java) is a parameter, and not "hidden" state, than an instance method can be pure if it doesn't change anything, and does not do IO. According to the Wikipedia definition of pure (en.wikipedia.org/wiki/Pure_function) the object also has to be immutable, as I said in the answer. Commented May 23, 2018 at 8:00
22

A pure method might as well be static. The two criteria for a pure method are, according to Wikipedia:

  1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.

  2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.

(emphasis mine)

There's no reason why this cannot apply to a non-static method. Making the method static would give a caller stronger guarantees that no instance state was being used, so it's probably better to make it static.


Depending on your perspective, one could view an instance method as simply a function taking an extra implicit argument: the instance itself. In this way, a non-static method could rely on instance state and be considered pure, provided it didn't rely on any external state (singletons etc) or produce side effects. Robert's answer puts it nicely. This is up to interpretation, but my person opinion is that such a method would be pure.

Voo put it nicely in the comments:

Why should a hidden this pointer be considered any more special than any other parameter to the function? That argument leads to a contradiction: Assume that
public static int pureFunc(MyInstance self) is pure, clearly the isomorph
public int pureFunc() would be pure as well.

6
  • on the other hand, if we wanted to avoid instance states influence to be pure, there would be no reason for the function not to be static, because it would not access any instance
    – Kaddath
    Commented May 22, 2018 at 13:23
  • 5
    This seems to rely on the fact that many languages hide the this pointer that's passed to instance methods. But ignoring that convention I don't see why a this pointer should be handled than any other input to the method. Actually by that definition it's also perfectly fine to access member variables as long as the method doesn't mutate them!
    – Voo
    Commented May 22, 2018 at 15:49
  • 1
    @Voo That would fail condition 1. If the object is mutate the method might return a different value. So: yes, you can access instance variables but only those that are immutable. This guarantees that no matter how the object is used a.method(some, arg) will always return same value.
    – Bakuriu
    Commented May 22, 2018 at 17:51
  • 3
    @Bakuriu I'd say that's up to interpretation. If we're saying that calling the function on an instance is the same as calling a function with that object as an implicit argument, I'd argue that calling the same function after the state has changed is not calling that function with the "same argument value(s)".
    – Michael
    Commented May 22, 2018 at 18:11
  • According to this definition, both of the methods the OP posted are not pure, since other threads could potentially change Rational while the method is executing, and Java's memory model makes no guarantees whether the effect are visible directly or not
    – Ferrybig
    Commented May 23, 2018 at 7:07
12

Conceptually, the only difference between a static method and an instance method is that instance method has a hidden parameter accessible through this keyword.

Therefore an instance method that does not mutate this is pure if it would otherwise qualify as a pure static method.

The issue here may be rather related to virtual dispatch which is prevented by static. A base class method may be pure whilst a derived class method may be impure while their contract in the Java type system is equal.

1
  • I would even add that there are multiple hidden parameters. Commented May 22, 2018 at 20:38
5

"Pure" basically means "depends only on its arguments and has no side-effects".

A static method doesn't have to be pure since it might access a static data structure. In the same way, an instance method may be pure since it doesn't access any instance variables.

So the concepts of "static" and "instance" aren't directly related to the concept of "pure".

1
  • 1
    "it might access a static data structure" and "it doesn't access any instance variables" are not related to purity either?
    – Bergi
    Commented May 22, 2018 at 12:52
1

This method:

public int add(int a, int b) {
   return a + b;
}

is not static but its return value does not depend on anything except the parameters. But because of this, add doesn't need to be an instance method at all!

I think this is what your textbook is getting at - instances methods that does not access the state or mutate the state may as well be static.

Instances methods are supposed to depend on the state of the object, otherwise it should be a static method. And static methods that doesn't depend on static states are pure.

1
  • You're right, but I don't think the textbook was saying such a method "may as well be static". I think the textbook was saying pure methods are necessarily static and had not considered this case.
    – Michael
    Commented May 22, 2018 at 16:13
0

There is no guarantee that a static method is pure. Technically a static method can have a static state. That's why your assumption

"a static method that depends only on its parameters and no other data"

is not true.

EDIT after Bergi comment

As I said before, the static keyword doesn't guarantee stateless. If you omit the static keyword in your quote, it still will be true.

So answering your question. Does a pure method have to be static? The answer is it depends.

There are benefits from making pure function static, i.e.:

  • It's a self-check, which guarantees that you don't (accidentally) change state in your class;

  • The method cannot be overridden. Which guarantees that the method won't change state in the future.

But on the other hand, it's difficult to mock static methods and it can be a problem during testing.

3
  • 2
    This quote doesn't say that all static methods depend only on their parameters and no other data. It starts a sentence that talks about methods which are static and which do depend only on their parameters and no other data.
    – Bergi
    Commented May 22, 2018 at 12:55
  • @Bergi probably I shall rephrase, I mean that there is no guarantee that a static method is pure.
    – dehasi
    Commented May 22, 2018 at 13:13
  • 1
    I understood what you mean. But that's not what the quote is saying.
    – Bergi
    Commented May 22, 2018 at 13:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.