A few days ago David Pollak did a blog showing the differences between a simple function to parse a string and return a number written in Scala in an "imperitive style" and in a "functional style." I commend the post and think many more like it are needed. It is very difficult for a person accustomed to imperitive programming to think in a functional way, and without simple examples comparing the code for common programming tasks, I think most programmers loose patience with functional programming. That all being said, I don't like David's example functional function:
- I think the conversion of the string to a list obfuscates what the function is doing, not to mention consumes resources unnecessarily.
- I find his use of pattern matching confusing, especially the way list operations are mixed in with it. I spent more time than I willing to admit trying to make sense of it.
- His nested function, p, has too many parameters.
object Parsely { def erikParseNumber(in: String): (Long, Int) = { if (in eq null) (0L, 0) else { val tin = in.trim() if (tin.length == 0) (0L, 0) else { val sign = if (tin.charAt(0) == '-') -1L else 1L def p(cur: Long, pos: Int): (Long, Int) = { if (pos == tin.length || !tin.charAt(pos).isDigit) (cur * sign, pos) else p((cur * 10L) + tin.charAt(pos).toLong - '0'.toLong, pos + 1) } p(0L, if (tin.charAt(0) == '-' || tin.charAt(0) == '+') 1 else 0) } } } }So I've done the following:
- I'm using the "pos" parameter as an index into the string, instead of making a list.
- In the nested function, I'm accessing some of the values from the enclosing scope instead of passing them as parameters. This reduces the number of parameters from 4 to 2.
- I'm using if/else expressions instead of pattern matching