Reputation: 4469
I expect the following code output with Seq(0)
, instead it returns a function ?
@ Seq(0).orElse(Seq(1))
res2: PartialFunction[Int, Int] = <function1>
I suspected at first that via syntax sugar it orElse
on apply
function, but it didn't since by trying:
@ Seq(0).apply.orElse(Seq(1))
cmd3.sc:1: missing argument list for method apply in trait SeqLike
....(omit)
I checked in IntellJ that there's no implicit conversion
.
What happens?
EDIT:
what I wish is:
Seq.empty.orElse(Seq(1)) == Seq(1)
Seq(0).orElse(Seq(1)) == Seq(0)
thanks @AndreyTyukin answer.
In one line, orElse
has different semantic in different type , now Seq
inherits PartialFunction
not Option
, so does the orElse
behavior.
Upvotes: 1
Views: 1293
Reputation: 44908
The Seq(0)
is treated as a PartialFunction
that is defined only at index 0
, and produces as result the constant value 0
if it is given the only valid input 0
.
When you invoke orElse
with Seq(1)
, a new partial function is constructed, that first tries to apply Seq(0)
, and if it finds nothing in the domain of definition of Seq(0)
, it falls back to Seq(1)
. Since the domain of Seq(1)
is the same as the domain of Seq(0)
(namely just the {0}
), the orElse
does essentially nothing in this case, and returns a partial function equivalent to Seq(0)
.
So, the result is again a partial function defined at 0
that gives 0
if it is passed the only valid input 0
.
Here is a non-degenerate example with sequences of different length, which hopefully makes it easier to understand what the orElse
method is for:
val f = Seq(1,2,3).orElse(Seq(10, 20, 30, 40, 50))
is a partial function:
f: PartialFunction[Int,Int] = <function1>
Here is how it maps values 0 to 4:
0 to 4 map f
// Output: Vector(1, 2, 3, 40, 50)
That is, it uses first three values from the first sequence, and falls back to the second sequence passed to orElse
for inputs 3
and 4
.
This also works with arbitrary partial functions, not only sequences:
scala> val g = Seq(42,43,44).orElse[Int, Int]{ case n => n * n }
g: PartialFunction[Int,Int] = <function1>
scala> 0 to 10 map g
res7 = Vector(42, 43, 44, 9, 16, 25, 36, 49, 64, 81, 100)
If you wanted to select between two sequences without treating them as partial functions, you might consider using
Option(Seq(0)).getOrElse(Seq(1))
This will return Seq(0)
, if this is what you wanted.
Upvotes: 5