A functional programming (FP) idiom, and therefore a Scala/FP idiom, is that functions and methods should not have side effects. As written in the book Programming in Scala:
A method’s only act should be to compute and return a variable.
Again, this means that a function should not have any side effects. It should take input variables, not modify those variables, then calculate and return something new. Unlike object-oriented programming, you should not change (mutate) the state of other variables, even if those variables are (a) variables of your class or (b) variables that were passed in to your function/method.
Note: For more recent coverage of this topic, please see my Scala Cookbook lesson, Create Scala methods that have no side effects (pure functions).
Benefits of functions not having side effects
If you're new to functional programming this may sound pretty hard core, but as someone who has been working with Scala and functional programming for a few months now, I do find it a good practice to try to follow. Here's a short list of benefits from this Scala programming idiom:
- Methods are less entangled.
- They are therefore more reliable and reusable.
- You won't change someone's variable accidentally, and they won't change yours.
- Make your programs easier to test.
I started to write why each of these statements is true, but they all come down to the same things:
- Because you aren't mutating the variables passed to you, you can't corrupt their values.
- Because your function has no other side effects other than calculating a value based on its inputs, there are no side effects you need to test.
Implementing the “no side effects” idiom
A simple way to begin implementing this idiom is to treat all your function arguments as immutable "val" fields (the same as "final" in Java).
The second way to implement this idiom is to make sure your function returns some sort of value. As you'll see in the last section of this article, if a function doesn't return anything (it is defined as returning Unit), the question becomes, What is this function doing? Clearly it must have side effects if it accepts input but doesn't return anything.
The third step to implement this Scala idiom is to refactor your code mercilessly. The old rule still applies:
A function should do one thing, and only one thing.
If you follow that general programming idiom, along with these other suggestions, the "no side effects" idiom will make a lot of sense.
Scala as a hybrid imperative and functional programming language
Unlike other functional programming languages, Scala is a hybrid (a) imperative and (b) functional programming language. Because it isn't a purely functional programming language, I find that it's easy to follow this "no side effects" idiom as much as possible, but I've also learned when not to follow it.
The Programming in Scala book uses the word "prefer" when discussing this idiom, and I think that's a healthy approach: You should prefer this form of programming, but don't try to force it where it doesn't fit. (That being said, if you're an object-oriented programmer, you'll be amazed where this idiom does fit if you consciously try to apply it to your code.)
If you have the book Programming in Scala, check out the example on pages 53-54 to see how the authors clean up an example using this "no side effects" idiom. It's a nice, simple example that demonstrates how following this idiom can simplify your code, even when you think it can't really be simplified any more.
Sign of a function with side effects
I'll leave you with one last quote, again from the Programming in Scala book:
The telltale sign of a function with side effects is that its result type (return type) is Unit.
If a function doesn't return a value, clearly it's doing something else:
- Mutating a variable that was passed in.
- Mutating a variable in the current class or somewhere else.
- Saving data to a database.
(I'm not a functional programming "purist", so all these actions are okay by me.)