Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should I avoid using local modifiable variables in Scala?

I'm pretty new to Scala and most of the time before I've used Java. Right now I have warnings all over my code saying that i should "Avoid mutable local variables" and I have a simple question - why?

Suppose I have small problem - determine max int out of four. My first approach was:

def max4(a: Int, b: Int,c: Int, d: Int): Int = {
  var subMax1 = a
  if (b > a) subMax1 = b

  var subMax2 = c
  if (d > c) subMax2 = d

  if (subMax1 > subMax2) subMax1
  else subMax2
}

After taking into account this warning message I found another solution:

def max4(a: Int, b: Int,c: Int, d: Int): Int = {
  max(max(a, b), max(c, d))
}

def max(a: Int, b: Int): Int = {
  if (a > b) a
  else b
}

It looks more pretty, but what is ideology behind this?

Whenever I approach a problem I'm thinking about it like: "Ok, we start from this and then we incrementally change things and get the answer". I understand that the problem is that I try to change some initial state to get an answer and do not understand why changing things at least locally is bad? How to iterate over collection then in functional languages like Scala?

Like an example: Suppose we have a list of ints, how to write a function that returns sublist of ints which are divisible by 6? Can't think of solution without local mutable variable.

like image 940
Oleksii Duzhyi Avatar asked Aug 02 '15 19:08

Oleksii Duzhyi


People also ask

Why we should not use VAR in Scala?

Performance: Sometimes using a var gives you the best possible performance. When people say that everything can be done without vars, that is correct in the sense that Scala would still be turing complete without vars. However, it doesn't change anything about the validity of the previous points.

Why is Val better than VAR in Scala?

The difference between val and var is that val makes a variable immutable — like final in Java — and var makes a variable mutable. Because val fields can't vary, some people refer to them as values rather than variables.

What is correct way of declaring variables in Scala?

The variable is declared with the following syntax in Scala as follows: val or val variable_name: variable_datatype = value; In the above syntax, the variable can be defined in one of two ways by using either the 'var' or 'val' keyword. It consists of 'variable_name' as your new variable, followed by a colon.

Which type of variable has permanent value throughout the Scala system?

Any constant value which can be assigned to the variable is called as literal/constant.


2 Answers

In your particular case there is another solution:

def max4(a: Int, b: Int,c: Int, d: Int): Int = {
  val submax1 = if (a > b) a else b
  val submax2 = if (c > d) c else d

  if (submax1 > submax2) submax1 else submax2
}

Isn't it easier to follow? Of course I am a bit biased but I tend to think it is, BUT don't follow that rule blindly. If you see that some code might be written more readably and concisely in mutable style, do it this way -- the great strength of scala is that you don't need to commit to neither immutable nor mutable approaches, you can swing between them (btw same applies to return keyword usage).

Like an example: Suppose we have a list of ints, how to write a function that returns the sublist of ints which are divisible by 6? Can't think of solution without local mutable variable.

It is certainly possible to write such function using recursion, but, again, if mutable solution looks and works good, why not?

like image 185
om-nom-nom Avatar answered Sep 25 '22 02:09

om-nom-nom


It's not so related with Scala as with the functional programming methodology in general. The idea is the following: if you have constant variables (final in Java), you can use them without any fear that they are going to change. In the same way, you can parallelize your code without worrying about race conditions or thread-unsafe code.

In your example is not so important, however imagine the following example:

val variable = ...
new Future { function1(variable) }
new Future { function2(variable) }

Using final variables you can be sure that there will not be any problem. Otherwise, you would have to check the main thread and both function1 and function2.

Of course, it's possible to obtain the same result with mutable variables if you do not ever change them. But using inmutable ones you can be sure that this will be the case.

Edit to answer your edit:

Local mutables are not bad, that's the reason you can use them. However, if you try to think approaches without them, you can arrive to solutions as the one you posted, which is cleaner and can be parallelized very easily.

How to iterate over collection then in functional languages like Scala?

You can always iterate over a inmutable collection, while you do not change anything. For example:

val list = Seq(1,2,3)
for (n <- list)
  println n

With respect to the second thing that you said: you have to stop thinking in a traditional way. In functional programming the usage of Map, Filter, Reduce, etc. is normal; as well as pattern matching and other concepts that are not typical in OOP. For the example you give:

Like an example: Suppose we have a list of ints, how to write a function that returns sublist of ints which are divisible by 6?

val list = Seq(1,6,10,12,18,20)
val result = list.filter(_ % 6 == 0)
like image 35
Álvaro Reneses Avatar answered Sep 26 '22 02:09

Álvaro Reneses