Domanda

When eval the data of Option, I tried to use fold[B](ifEmpty: => B)(f: A => B): B, but I'm a little confused by the result:

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

scala> Some(1).fold(() => "empty")(d => d.toString)()
res6: String = 1

The source code of this method:

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

I expected the result is a String, but got a <function0>, why?

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

I tried to mock this situation with following code:

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

According to the demo, it seems the result is affected by the scala type inference, is it?

È stato utile?

Soluzione

Because you passed () => "empty" as the first parameter, which is a function of type () => String; so that's what the type B is going to be. Note that the ifEmpty parameter is a call-by-name parameter.

If you don't want B to be () => String, but just String, then try this instead:

Some(1).fold("empty")(d => d.toString)

added after your edit: The main difference between your version 1 and version 2 demo is that in version 1, ifEmpty is a call-by-name parameter, and in version 2, g is not a call-by-name parameter, but a function of type A => B.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top