为什么Option.fold的结果是一个函数?

Eva*_* Y. 1 scala scala-2.10

当评估Option的数据时,我试图使用fold[B](ifEmpty: => B)(f: A => B): B,但我对结果有点困惑:

scala> Some(1).fold(() => "empty")(d => d.toString)
res5: () => String = <function0>

scala> Some(1).fold(() => "empty")(d => d.toString)()
res6: String = 1
Run Code Online (Sandbox Code Playgroud)

这个方法的源代码:

  @inline final def fold[B](ifEmpty: => B)(f: A => B): B =
    if (isEmpty) ifEmpty else f(this.get)
Run Code Online (Sandbox Code Playgroud)

我预计结果是String,但得到了<function0>,为什么?

==================

我尝试使用以下代码模拟这种情况:

case class Demo(size: Int)

// version 1, with the same fold method as Option
case class X [A <: Demo](data: A) {
    def fold[B](ifEmpty: => B)(f: A => B): B = {
        if(data.size < 3) ifEmpty else f(data)
    }
}

val demo = Demo(2)
val x = X(demo)

x.fold(() => "empty")(d => d.toString)   // the result is a function

// version 2
case class X [A <: Demo](data: A) {
    def fold[B](g: A => B)(f: A => B): B = {
        if(data.size < 3) g(data) else f(data)
    }
}

x.fold(g => g.toString)(f => f.toString)   // the result is a String
Run Code Online (Sandbox Code Playgroud)

根据演示,似乎结果受到scala类型推断的影响,是吗?

Jes*_*per 10

因为你() => "empty"作为第一个参数传递,这是一个类型的函数() => String; 所以这就是类型B.请注意,该ifEmpty参数是call-by-name参数.

如果你不想B成为() => String,只是String,然后尝试这样做:

Some(1).fold("empty")(d => d.toString)
Run Code Online (Sandbox Code Playgroud)

编辑后添加:版本1和版本2演示之间的主要区别在于版本1中ifEmpty是按名称调用参数,而在版本2中,g不是按名称调用参数,而是函数类型A => B.