Theodore Norvell
Theodore Norvell

Reputation: 16251

Is there a "for" syntax for flatmap?

Is there a "for" syntax for

c flatmap ( x => d flatmap (y => f(x,y) ) )

?

Because I've used Haskell in the past, I keep expecting the "for" syntax in Scala to mimic the "do" syntax of Haskell. This is probably an unrealistic expectation. In Haskell which I could write

do x <- c
   y <- d
   f(x, y)

Upvotes: 1

Views: 138

Answers (3)

Peter Neyens
Peter Neyens

Reputation: 9820

You could also map the last result on itself.

Using the same example as dhg:

val c = 1 to 3
val d = 4 to 6
def f(x: Int, y: Int) = Vector(x,y)

for { 
  x <- c
  y <- d
  z <- f(x,  y) 
} yield z
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)

Which corresponds to:

c flatMap ( x => d flatMap (y => f(x,y) map (identity) ) )

Upvotes: 4

Christophe Calv&#232;s
Christophe Calv&#232;s

Reputation: 692

Flattening may impact performance but i think scalac is clever enough to encode

for {
  x <- c
  y <- d
  z <- f(x,y)
} yield z

into

c flatMap { x => d flatMap { y => f(x,y) } }

This is annoying that the 'for' syntax is not as convenient as the 'do'-notation (writing _ <- someExpression instead of just someExpression in a for feels my heart with sadness).

Upvotes: 3

dhg
dhg

Reputation: 52701

You can just flatten the result:

val c = 1 to 3
val d = 4 to 6
def f(x: Int, y: Int) = Vector(x,y)

c flatMap ( x => d flatMap (y => f(x,y) ) )
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)

(for { x <- c; y <- d } yield f(x,y)).flatten
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)

Presumably this is a much less frequently used case since it is necessarily less common that the output of the for is flattenable. And sticking .flatten on the end is pretty easy, so having a special syntax for it seems unnecessarily complicated.

Upvotes: 3

Related Questions