IBM InfoSphere Streams Version 4.1.0

Side-effects

Code like y = (x = 5) + x−−; is hard to read and brittle because it has multiple side-effects in a single statement, so its meaning depends on the statement-internal evaluation order. The situation is even worse if the same expression calls multiple functions with side-effects. For example, the meaning of y = foo(x, 5) + bar(x); not only depends on evaluation order, but furthermore, depends on the definition of foo and bar. For example, x might be a list, and foo and bar might be push and pop. Statements with multiple side-effects are not only hard to understand for a human, but they are also hard to optimize for a compiler. In the absence of side-effects, compilers often optimize by reordering or even parallelizing independent code and eliminating redundant code. Fortunately, even in imperative languages like C and Java™, expression-internal side-effects are uncommon, and referential transparency is common. Unfortunately, without language support, this behavior s hard to establish in a compiler. SPL is designed to make side-effects more explicit, and to encourage a coding style where side-effects are less common.

There are features and design decisions that curb side-effects:

In addition, SPL has the following rules to curb side-effects:

Since function print does not modify x, a compiler can hoist the loop-invariant expression x * 100.0 out of the loop:
void test(float64 x, list<float64> z) {
  float64 loopInvariantTmp = x * 100.0;
  for (float64 y in z) {
    print(x);
    print(loopInvariantTmp / y);
  }
}

Besides enabling optimizations, making function parameters immutable by default also makes code easier to read and maintain.

If the ackermann function is stateless and has immutable parameters, then a compiler might eliminate one of the calls:
int32 ackermann(int32 m, int32 n) { /* do something expensive */ return 0; }
int32 test(int32 m, int32 n) {
  int32 x = ackermann(m, n);
  int32 y = x;
  return x + y;
}
To make statelessness easy to determine, all functions in SPL are stateless unless they are explicitly annotated with the stateful modifier.
Note: Functions that are stateless and have no mutable parameters are pure. Immutable parameters curb context-specific side-effects, whereas statelessness curbs context-independent side-effects.
When SPL was designed, categorically outlawing stateful functions altogether was considered. However, some stateful functions are useful. For example, print, or functions that interact with external resources such as databases. Furthermore, stateful functions can yield better performance through memorization. Therefore, it was decided to permit them in SPL, but the language design encourages mostly writing stateless functions.

Together, these rules mean that for most statements, the compiler is free to implement any internal expression evaluation order, and the user cannot observe the difference. The only exception is expressions that involve floating point numbers, which the compiler must always implement such that they evaluate left-to-right.