Exception handling in Scala functional programming - scala

I am going through Functional Programming In Scala ( Author :Paul Chiusano and Runar Bjarnarson), found below explanation for not using below total function for exception handling . It says if we are doing a lager computation we should not use, what exactly mean by it . Will you please explain giving a simple example . Thanks !!

Use types to communicate error cases rather than values
Lets a program called Foo is using the function mean. Unfortunately lets an empty IndexedSeq is sent as the argument to the mean function. In that case mean function would return onEmpty which is a Double.
Because mean returns a double when IndexedSeq is empty, the caller program (Foo program) cannot differentiate between the normal case (where the list is non empty) and the undefined case (where list is empty).
The problem with the mean function it returns Double in both undefined case and the normal case when list is non empty.
val someList = List.empty[Double]
val meanValue = mean(someList, -1)
if (meanValue == - 1) //undefined case else meanValue
The above way of checking the undefined value of the function mean is not recommended.
Author wants to communicate the undefined state by using some type.
Here is how we can do that
def mean(list: List[Double]): Option[Double] = {
if (list.isEmpty) None
else Some(list.sum / list.length)
}
The above mean function will return None when undefined case is encountered (list is empty) and does not rely on the unsafe communication of returning a value.
Foo program might stop computing when an undefined is return the mean function or Foo program might take a different branch when encounter by the undefined value (value returned by the mean function when list is empty). But Foo program has to reply on onEmpty value to check for the undefined case.

Imagine your program can receive a list List(-2.0, 0.0).
val list = List(-2.0, 0.0)
val theMean = mean(list, -1.0)
// now I want to handle the error case
if (theMean == -1.0)
println("mean can't be computed!") // wrong!
If mean would not take some silly default value but would return an Option[Double] or an Either[String,Double] or... it is no longer possible to make such a mistake.

Related

Why does the absence of an else block translate to Unit type return for a function?

I noticed there is a type mismatch caused in the line else if(r1 == 0 || divisors.tail.isEmpty || !divisors.tail.contains(r1)){newAcc}. Because there is no else clause to my if ... else if ...
def euclidianDivision(dividend:Int,divisor:Int):(Int,Int)={
val quotient = dividend/divisor
val remainder = dividend%divisor
(quotient,remainder)
}
def firstExpansion(dividend:Int,divisors:List[Int]):List[(Int,Int)]={
def firstExpansionIter(dividend:Int,divisors:List[Int], acc:List[(Int,Int)]):List[(Int,Int)]= {
val div1:Int = divisors.head
val (q1,r1):(Int,Int) = euclidianDivision(dividend,div1)
val newAcc:List[(Int,Int)] = acc:::List((div1,q1))
if (divisors.tail.contains(r1)){
firstExpansionIter(r1,divisors.tail,newAcc)
}else if(r1 == 0 || divisors.tail.isEmpty || !divisors.tail.contains(r1)){newAcc}
}
firstExpansionIter(dividend,divisors,List((0,0))).tail
}
Here's the error code:
Error:(32, 15) type mismatch; found : Unit required: List[(Int,
Int)]
}else if(r1 == 0 || divisors.tail.isEmpty || !divisors.tail.contains(r1)){newAcc}
I can correct this by adding the else clause, but how come if there is no outcome handled by default, the function tries to return a Unit?
N.B : Corrected code :
def firstExpansion(dividend:Int,divisors:List[Int]):List[(Int,Int)]={
def firstExpansionIter(dividend:Int,divisors:List[Int], acc:List[(Int,Int)]):List[(Int,Int)]= {
val div1:Int = divisors.head
val (q1,r1):(Int,Int) = euclidianDivision(dividend,div1)
val newAcc:List[(Int,Int)] = acc:::List((div1,q1))
if (divisors.tail.contains(r1)){
firstExpansionIter(r1,divisors.tail,newAcc)
}else if(r1 == 0 || divisors.tail.isEmpty || !divisors.tail.contains(r1)){newAcc}
else throw new RuntimeException("Something unexpected happened.")
}
firstExpansionIter(dividend,divisors,List((0,0))).tail
}
I can correct this by adding the else clause, but how come if there is no outcome handled by default, the function tries to return a Unit?
In Scala, unlike more "imperative" languages, (almost) everything is an expression (there are very few statements), and every expression evaluates to a value (which also means that every method returns a value).
This means that, for example, the conditional expression if (condition) consequence else differentConsequence is an expression that evaluates to a value.
For example, in this piece of code:
val foo = if (someRandomCondition) 42 else "Hello"
the then part of the expression will evaluate to 42, the else part of the expression will evaluate to "Hello", which means the if expression as a whole will evaluate to either 42 or "Hello".
So, what is the type of foo going to be? Well, in the then case, the value is of type Int and in the else case, the value is of type String. But, this depends on the runtime value of someRandomCondition, which is unknown at compile time. So, the only choice we have as the type for the whole if expression is the lowest common ancestor (technically, the weak least upper bound) of Int and String, which is Any.
In a language with union types, we could give it a more precise type, namely the union type Int | String. (Scala 3 has union types, so we could give the expression this exact type, although Scala 3 will not infer union types.) In Scala 3, we could even annotate it with the even more precise type 42 | "Hello", which is actually the type that TypeScript is going to infer for the equivalent conditional expression:
const foo = someRandomCondition ? 42 : "Hello"
Now, let's move forward towards the code in the question:
val bar = if (someRandomCondition) 42
What is the type of bar going to be? We said above that it is the lowest common ancestor of the types of the then and else branch, but … what is the type of the else branch? What does the else branch evaluate to?
Remember, we said that every expression evaluates to a value, so the else branch must evaluate to some value. It can't just evaluate to "nothing".
This is solved by a so-called unit value of a unit type. The unit value and type are called the "unit" value and type, because the type is designed in such a way that it can only possibly be inhabited by a single value. The unit type has no members, no properties, no fields, no semantics, no nothing. As such, it is impossible to distinguish two values of the unit type from one another, or put another way: there can only be one value of the unit type, because very other value of the unit type must be identical.
In many programming languages, the unit value and type use the same notation as a tuple value and type, and are simply identified with the empty tuple (). An empty tuple and a unit value are the same thing: they have no content, no meaning. In Haskell, for example, both the type and the value are written ().
Scala also has a unit value, and it is also written (). The unit type, however, is scala.Unit.
So, the unit value, which is a useless value, is used to signify a meaningless return value.
A related, but different concept in some imperative languages is the void type (or in some languages, it is more a "pseudo-type").
Note that "returns nothing" is different from "doesn't return", which will become important in the second part of this answer.
So the first half of the puzzle is: the Scala Language Specification says that
if (condition) expression
is equivalent to
if (condition) expression else ()
Which means that in the (implicit) else case, the return type is Unit, which is not compatible with List[(Int, Int)], and therefore, you get a type error.
But why does throwing an exception fix this?
This brings us to the second special type: Nothing. Nothing is a so-called bottom type, which means that it is a subtype of every type. Nothing does not have any value. So, what then, would a return type of Nothing signify?
It signifies an expression that doesn't return. And I repeat what I said above: this is different from returning nothing.
A method that has only a side-effect returns nothing, but it does return. Its return type is Unit and its return value is (). It doesn't have a meaningful return value.
A method that has an infinite loop or throws an exception doesn't return at all. Its return type is Nothing and it doesn't have a return value.
And that is why throwing an exception in the else clause fixes the problem: this means that the type of the else clause is Nothing, and since Nothing is a subtype of every type, it doesn't even matter what the type of the then clause is, the lowest common supertype of the type of the then clause and Nothing will always be the type of the then clause. (Think about it: the lowest common ancestor of a father and any of his children, grandchildren, great-grandchildren, etc. will always be the father himself. The lowest common ancestor of T and any subtype of T will always be T. Since Nothing is a subtype of all types, the lowest common ancestor of T and Nothing will always be T because Nothing is always a subtype of T, no matter what T is.)

Can Scala Option class be used as a function argument?

I have a recursive function which collects the leaf nodes of a kd-tree. This function has to take KdNode as an argument. The KdNode has the following class definition:
case class KdNode(value: (Double, Double), left: Option[KdNode], right: Option[KdNode], axis: Int, BB_A:BoundingBox, BB_B:BoundingBox)
The function definition where it is taken as an argument is:
def collectLeafNodes(t:KdNode): List[BoundingBox] = {
if(t == None) return
if (t.left == None && t.right == None) {
Some(listBoundingBox.::(t.BB_A,t.BB_B))
return
}
collectLeafNodes(t.left)
collectLeafNodes(t.right)}
Here, I encounter error on the last 2 lines saying: "Type mismatch, expected: KdNode, actual: Option[KdNode].
I am calling this function by building the kd-tree in variable "tree" and giving it as an argument:
val listofBoundingBoxes=collectLeafNodes(tree)
What is a possible workaround in this situation? In addition, I think there should be a way to pass the root node instead of tree to the collectLeafNodes function, is that possible given the tree is built in a separate function.
Thanks.
You ask, in the comments, how it can be done without return. Here's one way.
def collectLeafNodes(t :KdNode) :List[BoundingBox] =
List(t.BB_A, t.BB_B) :::
t.left.fold(List.empty[BoundingBox])(collectLeafNodes) :::
t.right.fold(List.empty[BoundingBox])(collectLeafNodes)
The result, without return, is the concatenation of 3 lists:
Since t is a KdNode and not an Option[KdNode], we know that the the BB values are real. That's the 1st List.
If t.left is None then the 2nd List is empty, otherwise the 2nd List is whatever the recursive call to collectLeafNodes(t.left) returns. (The argument is automatically supplied so it need not be specified.)
Same for the 3rd List with t.right
corrected for leaf nodes only
def collectLeafNodes(t :KdNode) :List[BoundingBox] = {
if (t.left.isEmpty && t.right.isEmpty) List(t.BB_A, t.BB_B)
else t.left .fold(List.empty[BoundingBox])(collectLeafNodes) :::
t.right.fold(List.empty[BoundingBox])(collectLeafNodes)
}
You can map over the option object:
val res: List[BoundingBox] = t.left.map(collectLeafNodes).getOrElse(List())
Because t.right is type of Option and not type of Kdnode.
You can unwrap Option to solve this e.g.
collectLeafNodes(t.right.get)}
collectLeafNodes(t.right.orElse(None)}
Hope this helps

Implicit String to Seq[Char] pattern matching fail

Warning - this is a code which deals with Codility BinaryGap task - just to warn as this may spoil something to somebody.
I have a piece of code, like
#tailrec
def count2(max:Int, count:Int, d:Seq[Char]):Int = d match {
case '1' :: s => count2(Math.max(max, count), 0, s)
case '0' :: s => count2(max, count+1, s);
case Nil => max
}
I call it like
println(Solution.count2(0, 0, Seq('1', '0')))
println(Solution.count2(0, 0, "10"))
It compiles, however the second call does not work - throwing "Match not found 10" And I cannot understand why. There is a similar question around that topic which states, that explicit conversion is needed. However, I feel like I do have one in form of a method parameter type.
Debugger clearly states that d variable is of type WrappedString - which should do the job. But apparently, it does not.
What is going on here?
Your pattern matching is working only on a the type List[Char] while you are passing an object of type Seq[Char]. Therefore you will never actually match on the very first call. The reason it compiles is that match is not exhaustive for Seq. It is, however, exhaustive for List.
Update:
Let me point out two things:
The default constructor for Seq produces a List. So the first example "works."
The String you've given is implicitly convertable to a Seq[Char] but it is not a List! Hence, it will give you your match error.

Scala: understanding how to make my method return the proper return type of Array

I have written the following Scala code:
class MyTestApi {
private def toCPArray(inputStr: String): Array[Int] = {
val len = inputStr.length
//invoke ofDim of Scala.Array
val cpArray = Array.ofDim[Int](inputStr.codePointCount(0, len))
var i = 0
var j = 0
while (i < len) {
cpArray(j += 1) = inputStr.codePointAt(i)
i = inputStr.offsetByCodePoints(i, 1)
}
cpArray
}
}
This is what I want to accomplish:
I would create an instance of class MyTestApi and then invoke the method toCPArray and pass to it a parameter of type String. I would then like this method to return me an `Array[Int].
However as it stands now, the Scala IDE is complaining about this line:
**cpArray(j += 1) = inputStr.codePointAt(i)**
type mismatch; Found: Unit required: Int
Two things I would like to accomplish are:
How would I fix this method? (or is it a function)
My hope is, after I understand what it takes to fix this method (or function) I will be able to return the appropriate type. Also, I should be in better position to understand the difference between a method and a function.
So far my research on stackoverflow and Martin Odersky's book seems to suggests to me that what I wrote is a method because it is invokded on an instance of the underlying class. Is my understanding right on that?
After it is fixed, how can i rewrite it in a more Scalaesque way, by getting rid of the var. The code looks more C or java like right now and is a little long in my opinion, after all that I have studied about Scala so far.
Thanks for any help in refactoring the above code to accomplish my learning objectives.
You are calling cpArray.update with an assignment statement which evaluates to Unit when it expects an Integer. You need to call it with an Integer:
j += 1
cpArray(j) = inputStr.codePointAt(i)
Many questions in one. I try to answer them all.
First of all as Jörg pointed out, moving the assignment makes the code work. Contrary to Java and C, Scala's assignment doesn't return the assigned value but Unit.
Now for making it idiomatic. Scala's String can be seem as IndexedSeq[Char], meaning you can generally treat them as IndexedSeqs. So you doing do something like:
inputStr.map{ x => x.toInt }.toArray
This will return an Array[Int]. Notice it will only work for 16-bits char representations. Hopefully it will help in giving an idea of idiomatic Scala, even not being a perfect solution.
For the difference between methods and functions, it's simple: methods are generally defs in a class. Functions one the other hands are Objects in the JVM sense. For example, the above map could be defined like:
def map(f: Function1[Char, Int]):IndexedSeq[Int]
// or
def map(f: Char => Int):IndexedSeq[Int]
Both are the same, => desugars to one of the scala.FunctionN (N from 0 to 22 inclusive).
And x => x.toInt is desugared in a similar way into a instance of scala.Function1. See it's Scaladoc.
So, functions are objects of type scala.FunctionN.
Note: to keep things simple I omitted a few details like type parameters, vals (which often compiles to JVM methods) and probably a few more details.

Ending a for-comprehension loop when a check on one of the items returns false

I am a bit new to Scala, so apologies if this is something a bit trivial.
I have a list of items which I want to iterate through. I to execute a check on each of the items and if just one of them fails I want the whole function to return false. So you can see this as an AND condition. I want it to be evaluated lazily, i.e. the moment I encounter the first false return false.
I am used to the for - yield syntax which filters items generated through some generator (list of items, sequence etc.). In my case however I just want to break out and return false without executing the rest of the loop. In normal Java one would just do a return false; within the loop.
In an inefficient way (i.e. not stopping when I encounter the first false item), I could do it:
(for {
item <- items
if !satisfiesCondition(item)
} yield item).isEmpty
Which is essentially saying that if no items make it through the filter all of them satisfy the condition. But this seems a bit convoluted and inefficient (consider you have 1 million items and the first one already did not satisfy the condition).
What is the best and most elegant way to do this in Scala?
Stopping early at the first false for a condition is done using forall in Scala. (A related question)
Your solution rewritten:
items.forall(satisfiesCondition)
To demonstrate short-circuiting:
List(1,2,3,4,5,6).forall { x => println(x); x < 3 }
1
2
3
res1: Boolean = false
The opposite of forall is exists which stops as soon as a condition is met:
List(1,2,3,4,5,6).exists{ x => println(x); x > 3 }
1
2
3
4
res2: Boolean = true
Scala's for comprehensions are not general iterations. That means they cannot produce every possible result that one can produce out of an iteration, as, for example, the very thing you want to do.
There are three things that a Scala for comprehension can do, when you are returning a value (that is, using yield). In the most basic case, it can do this:
Given an object of type M[A], and a function A => B (that is, which returns an object of type B when given an object of type A), return an object of type M[B];
For example, given a sequence of characters, Seq[Char], get UTF-16 integer for that character:
val codes = for (char <- "A String") yield char.toInt
The expression char.toInt converts a Char into an Int, so the String -- which is implicitly converted into a Seq[Char] in Scala --, becomes a Seq[Int] (actually, an IndexedSeq[Int], through some Scala collection magic).
The second thing it can do is this:
Given objects of type M[A], M[B], M[C], etc, and a function of A, B, C, etc into D, return an object of type M[D];
You can think of this as a generalization of the previous transformation, though not everything that could support the previous transformation can necessarily support this transformation. For example, we could produce coordinates for all coordinates of a battleship game like this:
val coords = for {
column <- 'A' to 'L'
row <- 1 to 10
} yield s"$column$row"
In this case, we have objects of the types Seq[Char] and Seq[Int], and a function (Char, Int) => String, so we get back a Seq[String].
The third, and final, thing a for comprehension can do is this:
Given an object of type M[A], such that the type M[T] has a zero value for any type T, a function A => B, and a condition A => Boolean, return either the zero or an object of type M[B], depending on the condition;
This one is harder to understand, though it may look simple at first. Let's look at something that looks simple first, say, finding all vowels in a sequence of characters:
def vowels(s: String) = for {
letter <- s
if Set('a', 'e', 'i', 'o', 'u') contains letter.toLower
} yield letter.toLower
val aStringVowels = vowels("A String")
It looks simple: we have a condition, we have a function Char => Char, and we get a result, and there doesn't seem to be any need for a "zero" of any kind. In this case, the zero would be the empty sequence, but it hardly seems worth mentioning it.
To explain it better, I'll switch from Seq to Option. An Option[A] has two sub-types: Some[A] and None. The zero, evidently, is the None. It is used when you need to represent the possible absence of a value, or the value itself.
Now, let's say we have a web server where users who are logged in and are administrators get extra javascript on their web pages for administration tasks (like wordpress does). First, we need to get the user, if there's a user logged in, let's say this is done by this method:
def getUser(req: HttpRequest): Option[User]
If the user is not logged in, we get None, otherwise we get Some(user), where user is the data structure with information about the user that made the request. We can then model that operation like this:
def adminJs(req; HttpRequest): Option[String] = for {
user <- getUser(req)
if user.isAdmin
} yield adminScriptForUser(user)
Here it is easier to see the point of the zero. When the condition is false, adminScriptForUser(user) cannot be executed, so the for comprehension needs something to return instead, and that something is the "zero": None.
In technical terms, Scala's for comprehensions provides syntactic sugars for operations on monads, with an extra operation for monads with zero (see list comprehensions in the same article).
What you actually want to accomplish is called a catamorphism, usually represented as a fold method, which can be thought of as a function of M[A] => B. You can write it with fold, foldLeft or foldRight in a sequence, but none of them would actually short-circuit the iteration.
Short-circuiting arises naturally out of non-strict evaluation, which is the default in Haskell, in which most of these papers are written. Scala, as most other languages, is by default strict.
There are three solutions to your problem:
Use the special methods forall or exists, which target your precise use case, though they don't solve the generic problem;
Use a non-strict collection; there's Scala's Stream, but it has problems that prevents its effective use. The Scalaz library can help you there;
Use an early return, which is how Scala library solves this problem in the general case (in specific cases, it uses better optimizations).
As an example of the third option, you could write this:
def hasEven(xs: List[Int]): Boolean = {
for (x <- xs) if (x % 2 == 0) return true
false
}
Note as well that this is called a "for loop", not a "for comprehension", because it doesn't return a value (well, it returns Unit), since it doesn't have the yield keyword.
You can read more about real generic iteration in the article The Essence of The Iterator Pattern, which is a Scala experiment with the concepts described in the paper by the same name.
forall is definitely the best choice for the specific scenario but for illustration here's good old recursion:
#tailrec def hasEven(xs: List[Int]): Boolean = xs match {
case head :: tail if head % 2 == 0 => true
case Nil => false
case _ => hasEven(xs.tail)
}
I tend to use recursion a lot for loops w/short circuit use cases that don't involve collections.
UPDATE:
DO NOT USE THE CODE IN MY ANSWER BELOW!
Shortly after I posted the answer below (after misinterpreting the original poster's question), I have discovered a way superior generic answer (to the listing of requirements below) here: https://stackoverflow.com/a/60177908/501113
It appears you have several requirements:
Iterate through a (possibly large) list of items doing some (possibly expensive) work
The work done to an item could return an error
At the first item that returns an error, short circuit the iteration, throw away the work already done, and return the item's error
A for comprehension isn't designed for this (as is detailed in the other answers).
And I was unable to find another Scala collections pre-built iterator that provided the requirements above.
While the code below is based on a contrived example (transforming a String of digits into a BigInt), it is the general pattern I prefer to use; i.e. process a collection and transform it into something else.
def getDigits(shouldOnlyBeDigits: String): Either[IllegalArgumentException, BigInt] = {
#scala.annotation.tailrec
def recursive(
charactersRemaining: String = shouldOnlyBeDigits
, accumulator: List[Int] = Nil
): Either[IllegalArgumentException, List[Int]] =
if (charactersRemaining.isEmpty)
Right(accumulator) //All work completed without error
else {
val item = charactersRemaining.head
val isSuccess =
item.isDigit //Work the item
if (isSuccess)
//This item's work completed without error, so keep iterating
recursive(charactersRemaining.tail, (item - 48) :: accumulator)
else {
//This item hit an error, so short circuit
Left(new IllegalArgumentException(s"item [$item] is not a digit"))
}
}
recursive().map(digits => BigInt(digits.reverse.mkString))
}
When it is called as getDigits("1234") in a REPL (or Scala Worksheet), it returns:
val res0: Either[IllegalArgumentException,BigInt] = Right(1234)
And when called as getDigits("12A34") in a REPL (or Scala Worksheet), it returns:
val res1: Either[IllegalArgumentException,BigInt] = Left(java.lang.IllegalArgumentException: item [A] is not digit)
You can play with this in Scastie here:
https://scastie.scala-lang.org/7ddVynRITIOqUflQybfXUA