moshe beeri
moshe beeri

Reputation: 2037

scala curried function with yield

I try to learn curried functions in Scala, see the code

  def isEven(v: Int): Boolean = v % 2 == 0

  def evens(numbers: List[Int])(even: Int => Unit) {
    for (number <- numbers; if isEven(number)) {
      even(number)
    }
  }

  val my = List.range(1, 100)

  evens(my){println(_)} // works fine and prints the even numbers as expected 

  val recurse = evens(my) { yield _ } //compilation error

I would like to get the result as yield accumulation, but I can not fined how to do that in Scala documentation nor any example. Any idea?

Upvotes: 1

Views: 247

Answers (2)

moshe beeri
moshe beeri

Reputation: 2037

Scala curried functions are not interned to be used with yield as I have tried in my question, for that purpose there is no need to use curried functions at all as you simply ca to the following:

  def evens(numbers: List[Int]) : List[Int] = {
     for (number <- numbers if (number % 2) == 0) yield number
  }

and then:

    val my = List.range(1, 100)
    evens(my).foreach(f => println(f))

Thanks to @RexKerr for his solution showing how to utilize generics and curried functions to yield and return the curried results.

Upvotes: 0

Rex Kerr
Rex Kerr

Reputation: 167911

You cannot abstract over the two forms of for usage. One desugars to a foreach while the other to map and (possibly) flatMap; the return types are also different.

You can write two functions, or you can write a generic method and ignore the return value:

def evens[A](numbers: List[Int])(even: Int => A): List[A] = {
  for (number <- numbers if (number % 2) == 0) yield even(number)
}

Now if you want the list back unchanged you use the identity function:

val e = evens(my)(identity)
val e = evens(my)(x => x)   // Equivalent

If you want to do something to it, you ignore the return value:

evens(my)(println)

Upvotes: 4

Related Questions