0

I have two variables that are optional double and I want to consider them as 0 when they are None

var x: Option[Double] = Option(0)
var y: Option[Double] = Option(0)
println("Expected 0 : "+(x ++ y).reduceOption(_ - _)) // 0

x = Option(4)
y = Option(0)
println("Expected 4 : "+(x ++ y).reduceOption(_ - _)) // 4

x = Option(0)
y = Option(4)
println("Expected -4 : "+(x ++ y).reduceOption(_ - _)) // -4

x = Option(4)
y = None
println("Expected 4 : "+(x ++ y).reduceOption(_ - _)) // 4

x = None
y = Option(4.0)
println("Expected -4 : "+(x ++ y).reduceOption(_ - _)) // 4

The last one I am expecting -4 but I get 4.

If I use

(for (i <- x; j <- y) yield i - j)

then I get None.

Also If I try

x.getOrElse(0) - y.getOrElse(0) // value - is not a member of AnyVal

then I get error value - is not a member of AnyVal

trincot
  • 317,000
  • 35
  • 244
  • 286
Ranveer Singh
  • 27
  • 1
  • 7
  • 2
    `None ++ Option(4.0)` evaluates to `Iterable(4.0)`. Since there is only one element in the collection there is nothing to reduce, so no subtraction takes place. – jwvh Sep 20 '21 at 18:27
  • 3
    `0` is not a `Double`. For that you need `0.0` or `0D` or `0d`. Try that in your `getOrElse()` calls. – jwvh Sep 20 '21 at 18:32

1 Answers1

3

The (x ++ y).reduceOption(_ - _) is a perfect example of how to confuse people in Scala IMHO. It's not immediate that ++ operates on Option because they are also Seq.

That being said, as already suggested in the comments, the straightforward way would be to use getOrElse:

x.getOrElse(0d) - y.getOrElse(0d)

You need to precise the d to have an Double otherwise, you get an AnyVal because AnyVal is the only common parent type of Int (from the getOrElse) and Double (value in the option).

Gaël J
  • 11,274
  • 4
  • 17
  • 32