1

How is a below printed as None as the max is 3 here

val firstNum: Option[Int] = None
val secondNum: Option[Int] = Some(3)

val a = for {
  f <- firstNum
  s <- secondNum

} yield Math.max(f, s)

println(a)

output

None
Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
supernatural
  • 1,107
  • 11
  • 34
  • 2
    Because first `<-` is actually a `flatMap` method, and it is called only if the `Option` is present (its value is `Some`). – insan-e Feb 03 '21 at 15:51
  • 1
    It's because `option` obey all Monads law including left identity, meaning `None.flatMap(f)` always returns None. – Ivan Kurchenko Feb 03 '21 at 15:51
  • okay but, firstNum when flattened, it is still None but the other one, secondNum after flattened, it will be 3.. and then 3 is the max .. – supernatural Feb 03 '21 at 15:54
  • 1
    After firstNum is flattened and you get None, the evaluation stops there. When you attempt to call flatMap again on None, you still get None, so everything after "f <- firstNum" doesn't matter. – Allen Han Feb 03 '21 at 17:11

2 Answers2

4

As in comment section was mentioned, your are using for-comprehension construction, which under the hood invokes flatMap method, which according to left identity monad law always works like this: None.flatmap(f) == None.

If you you want to find max between two Option[Int] and ignore if any of them absent, try to:


val firstNum: Option[Int] = None
val secondNum: Option[Int] = Some(3)
​
println(List(firstNum, secondNum).flatten.max)

Scatie: https://scastie.scala-lang.org/UbCy36hHS3iVLKEdqzqUCw

Ivan Kurchenko
  • 4,043
  • 1
  • 11
  • 28
4

Just to add on top of the great answer by @IvanKurchenko. .max might throw an exception in case there are no elements in the List. For example:

List[Option[Int]](None).flatten.max

will throw an exception:

java.lang.UnsupportedOperationException: empty.max

Instead, you can use maxOption:

List(Some(3), None).flatten.maxOption

which will provide Some(3), and

List[Option[Int]](None).flatten.max

will provide None.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35