Null pointer exception solution
Nice introduction here: https://scalac.io/null-pointer-exception-npe/
Scala solution
val option: Option[Int] = Some(4)
val empty: Option[Int] = None
That has vast impact on syntax and solution of more complicated things (some intro at the end of this article). That’s the right, functional way of dealing with absence (NPE).
Tail recursion
To avoid stack overflow (try highly nested recursion in Python functions!) in Scala use tail recursion:
def factorial(n: Int): Int =
if (n <= 1) 1
else {
println("Computing factorial of " + n + " I first need factorial of " + (n - 1))
val result = n * factorial(n - 1)
println("Computed factorial of " + n)
result
}
// factorial(4700) // gonna crash!
def factorialUsingTailRec(n: Int): BigInt = {
@tailrec
def factHelper(x: Int, accumulator: BigInt): BigInt =
if (x <= 1) accumulator
else factHelper(x - 1, x * accumulator) // TAIL RECURSION - use recursive call as last expression
factHelper(n, 1)
}
println(factorialUsingTailRec(6000))
Tail recursion saves memory, no need to use new and new stack frames.
FP
Main problem to write code in Scala is to learn functional programming for me. Of course, some concepts like immutability I’m familiar with (you can, or even you have to, use immutability also in OOP to avoid side-effects - nightmare for every legacy projects I saw in my life). But still, knowing Scala syntax is not enough. Yep, you can use OOP principles or even write imperative code in Scala, but if so there is no need to use this language.
Example with pseudocode:
/*
if (host != null):
if (port != null):
return Connection.apply(host, port)
return null
*/
And Scala one-liner implementation (using Option
interface mentioned in the first paragraph of this post):
val connection: Option[Connection] = host.flatMap(h => port.flatMap(p => Connection.apply(h, p)))
Such chaining is nice way to resolve this problem but even better (also more-readable) is for-comprehensions:
val connectionStatus = for {
h <- config.get("host")
p <- config.get("port")
connection <- Connection(h, p)
} yield connection.connect
println(connectionStatus)
Yep, rather not easy at first look, but nobody said it will be easy :)