@Pure Specification

Declares that a single method on a class is "Pure".

See the Wikipedia definition, from which the following is derived. Essentially:

Pure4J makes the distinction between implementation purity, and interface purity, as described below.

1. Implementation Purity.

A pure implementation will:

  1. Only call other methods (or constructors) regarded to be implementationPure. Errors will be reported if a pure method accesses code not regarded to be implementation pure.
  2. Can access only immutable, final state within the system (for prevention of side-effects). (see @ImmutableValue Specification)

2. Parameter Mutability (Interface Purity)

  1. By default, adding @Pure will check that the method only accepts immutable parameters (see {@link ImmutableValue}). This ensures that the pure methods are Thread Safe and means that, once invoked the state of their arguments cannot be changed while the method is running. Otherwise, this would impact the determinism constraint.
  2. (untested) If the pure method is non-static, 'this' must also be immutable.
  3. Pure methods are allowed to access other methods that are not interface pure. (e.g. pure private methods on a class can be only implementation pure)
  4. Only methods which are both implementation pure and interface pure are reported in the resulting public pure interface of the class. Thus, non-pure code should only access pure code that is both implementation and interface pure.

Defaults

By adding the @Pure annotation, you expect both interface and implementation purity to be observed in the method. Errors will be reported if these constraints are not met.

Overriding Purity Checking

You can disable purity checking (of both kinds) by adding the Enforcement argument on this annotation.

Overriding Interface Purity Only

You can disable the interface purity check by additionally adding the @PureParameters annotation. By setting the Enforcement argument on this annotation you can either:

Runtime Interface Purity Checking

If you are writing code that uses generics, or implements an interface that takes arguments which are non-immutable values, you may need to test the interface purity at runtime.

You can do this by adding Pure4J.immutable(<args>) as:

Alternatively, you can use the Pure4J.unsupported() method to throw an UnsupportedOperationException which will also disable parameter checking.

Example

	 	public String testParam2Good(Object in1, Object in2) {
			Pure4J.immutable(in1, in2);
			return in1.toString() + in2.toString();
		}
 	

On Static Methods

Since @ImmutableValue and @MutableUnshared are class-level annotations, and specify the purity requirements for instance methods only, one common use-case for the @Pure annotation is in declaring static methods as being pure.

Caveats

Use of reflection within your code can break these guarantees. The compile-time checker will make no attempt to ensure semantics where reflection is involved. (In fact, this is undecideable).

Java Language Purity

Lots of the methods in the Java language are pure, and can be used by your pure code. For example:

Other External Libraries

Construction and Use

Pure code is free to construct @MutableUnshared objects, or @ImmutableValue objects, since the constructors for both of these types of objects are registed pure.