List.orElse 的 Scala 意外输出

Scala unexpected output for List.orElse

我希望使用 Seq(0) 输出以下代码,而不是 returns 一个函数 ?

@ Seq(0).orElse(Seq(1))
res2: PartialFunction[Int, Int] = <function1>

起初我怀疑是通过语法糖 orElseapply 函数上,但它并没有通过尝试:

@ Seq(0).apply.orElse(Seq(1))
cmd3.sc:1: missing argument list for method apply in trait SeqLike
....(omit)

我在 IntellJ 中检查过没有 implicit conversion
会发生什么?


编辑: 我想要的是:
Seq.empty.orElse(Seq(1)) == Seq(1)
Seq(0).orElse(Seq(1)) == Seq(0)


感谢@AndreyTyukin 的回答。
在一行中,orElse 在不同类型中具有不同的语义,现在 Seq 继承 PartialFunction 而不是 OptionorElse 行为也是如此。

仅在索引 0 处定义的 Seq(0) is treated as a PartialFunction,如果给定唯一有效输入 0,则生成常量值 0 作为结果。 =39=]

当您使用 Seq(1) 调用 orElse 时,将构造一个新的部分函数,​​它首先尝试应用 Seq(0),如果它在 [的定义域中找不到任何内容=15=],它回落到 Seq(1)。由于 Seq(1) 的域与 Seq(0) 的域相同(即只是 {0}),因此 orElse 在这种情况下基本上什么都不做,而 return 是等同于 Seq(0).

的偏函数

因此,结果再次是在 0 处定义的偏函数,如果传递给唯一有效输入 0,则该函数给出 0 0


这是一个具有不同长度序列的非退化示例,希望它能让您更容易理解 orElse 方法的用途:

val f = Seq(1,2,3).orElse(Seq(10, 20, 30, 40, 50))

是偏函数:

f: PartialFunction[Int,Int] = <function1>

这是它如何将值 0 映射到 4:

0 to 4 map f

// Output: Vector(1, 2, 3, 40, 50)

也就是说,它使用第一个序列的前三个值,然后回退到传递给 orElse 的第二个序列,用于输入 34


这也适用于任意偏函数,而不仅仅是序列:

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)

如果您想在两个序列之间 select 而不将它们视为部分函数,​​您可以考虑使用

Option(Seq(0)).getOrElse(Seq(1))

这将 return Seq(0),如果这是你想要的。