Signs that you are thinking functionally


#1

Hi,

I come form Java background, and been trying to learn Scala for almost one year now and imbibe functional paradigm. But even after putting in decent amount of efforts and time, I still feel that while programming I think java way, or I would say that I feel more comfortable coding in Java than Scala.

So I am not sure if I am progressing in right direction.
What are the signs which can tell person that he/she is thinking functional while programming?


#2

I don’t know that there’s any single clear answer to that, given that we don’t have any real consensus on what “functional programming” means.

But I’d say that step one is usually immutability: if you can get comfortable with few or no var members in your code, you’re moving in the right direction…


#3

The key is to think in terms of expressions instead of (mutable) variables and statements. Using immutable collections and minimizing the use of var tends to push you in the right direction.

For instance, contrast:

var v = 0
if (cond) v = 42

with

val v = if (cond) 42 else 0

(the var is gone and the if has become an expression instead of a statement)

Or:

def removeAll[A](list: List[A], set: Set[A]): Set[A] = {
  var res = set
  for (x <- list)
    res -= x
  res
}

with

def removeAll[A](list: List[A], set: Set[A]): Set[A] = list match {
  case Nil => set
  case x :: l => removeAll(l, set - x)
}

(the var is gone and the statement res -= x has become an expression set - x)


#4

I really like both of the answers given so far. I’ll add one warning to the first one, in addition to not using var, don’t use any mutable collections. That includes Array. In some cases you might be forced to by the library, like the split method on String, but when you are in that situation, just make sure that you don’t do assignments to mutate the array.

How do you do both of these things? How do you write code that doesn’t mutate and that uses expressions instead of statements? A lot of the time you will either use collection methods (map, filter, reduce, fold, etc.) or recursion. So back to your original question, when you find that your preference is to do things through one of these other methods with no mutation instead of declaring a mutable variable and using a loop, then you have passed a significant hurdle in terms of thinking functionally.

(I have to note that in Scala you can use a for and still be functional as long as the for has a yield and you are using it as an expression so you don’t mutate values inside of it.)


#5

Yes, you should try to avoid vars in general, but keep in mind that not all vars are created equal. A local var in a class method (def) does no real harm (unless you try to run that method in parallel). A class with local vars in its methods can still be immutable so long as there are no vars in the class itself (i.e., var data fields in the class body outside of any method).

Try to use immutable case classes as much as possible, and use the “copy” method extensively to return a modified version of the class with part modified and the rest unchanged.


#6

Thanks for code snippets.
Second version of removeAll is tail-recursive…right?


#7

Yes, it is. As a local function, it’d be optimized by the compiler.


#8

The following seems to do it as well

def remove[A](list: List[A], set: Set[A]) =
  set.filterNot(x => list.contains(x))

#9

Another functional solution

def remove[A](list: List[A], set: Set[A]) = set -- list

#10

Yes, but much less efficiently, as you iterate over the set and look up inside the list instead of the other way around.


#11

A mutable closure around a local variable can be a tricky bug indeed, especially with multiple threads. But it can already be confusing without concurrency:

trait T {
  def get: Int
}

def process(x1: Int, x2: Int): (T, T) = {
  var i = 5
  val t1 = new T {
    def get: Int = x1 * i
  }
  i = 42
  val t2 = new T {
    def get: Int = x2 * i
  }
  (t1, t2)
}

val (t1, t2) = process(10, 100)

Here, t1.get is 420, not 50. The fact that the i = 42 assignment affects the behavior of t1.get is not necessarily obvious.

The example might seem contrived, but I’ve seen this happen in actual code, usually with a var declared outside a loop. (Note that Java won’t let you reassign a local variable on which you have a closure, thus avoiding the danger.)

In short, it’s not that var is evil or should be avoided at all cost, it’s just that it tends to require more careful thinking.


#12

That’s interesting, but why would you declare i as a var if you don’t want to have control over it in the “get” function? It seems to me you are getting what you want here, otherwise you would simply declare i as a val. Perhaps that is your point, but I see this example as more of a warning about closures than about local vars.


#13

The issue is closure over a var; over a val (like in Java) wouldn’t be a problem. (Isn’t that what you had in mind when you said concurrent calls would be a problem?)

The example I saw recently was more like this:

trait Match {
  def lineNum: Int
  def content: String
}

def search(lines: Iterator[String]): List[Match] = {
  val matches = new ListBuffer[Match]
  var i = 0
  for (line <- lines) {
    i += 1
    if (cond) {
      matches += new Match {
        def lineNum = i
        def content = line
      }
    }
  }
  matches.result()
}

This doesn’t work: the line numbers are incorrect (even though the line contents are fine). It may be obvious to you, but it can confuse the heck out of Java programmers who haven’t heard much about closures.

(Note: zipWithIndex comes in handy for this particular scenario.)


#14

A local var defined inside a method is perfectly thread-safe as long as it is not used inside an object that escapes from the method or thread, such as (closure around) a local def, a function object, or some other inner object.