1

Given these definitions:

val guys = List("Albert", "Tom")
val girls = List("Mary", "Stacy", "Josie")

val optRoom: Option[String] = Some("Room 303")

This evaluates to me expected List[String]:

for {
  guy <- guys
  girl <- girls
  room <- optRoom
} yield {
  s"$guy dances with $girl in $room"
}

Turning things a bit inside the loop, I would expect this to evaluate to an Option[List[String]], but it does not even compile:

for {
  room <- optRoom
  guy <- guys
  girl <- girls
} yield {
  s"$guy dances with $girl in $room"
}  

Why not? What am I missing? (I know I can convert optRoot to a sequence / list / iterable, but it's not what I want)

How should I rewrite my code to get Option[List[String]]?

Sebastian N.
  • 1,875
  • 14
  • 25

2 Answers2

2

Your second example is equivalent to

optRoom flatMap { room =>
  guys flatMap { guy =>
    girls map { girl =>
      s"$guy dances with $girl in $room"
    }
  }
}

Which doesn't work because you're not returning an Option to optRoom.flatMap.

If you want an Option[List[String]], then you want to be calling optRoom.map, not flatMap, because you want the result wrapped in an Option:

for {
  room <- optRoom
} yield for {
  guy <- guys
  girl <- girls
} yield {
  s"$guy dances with $girl in $room"
}
Dan Getz
  • 7,743
  • 6
  • 29
  • 60
  • Thanks for the answer. You say: " because you're not returning an `Option` to `optRoom.flatMap`". Would it be possible to do so? Would it make sense? – Sebastian N. May 22 '14 at 10:26
  • It would make sense if the result you're calculating in the case `optRoom` is not `None` is naturally an `Option[something]`. In your case it's naturally a `List[String]`. So you could turn that into `Some[List[String]]`, but that is just using `flatMap` to emulate `map`. – Dan Getz May 22 '14 at 10:31
1

You can do:

optRoom.map(room => for {
  guy <- guys
  girl <- girls
} yield s"$guy dances with $girl in $room")

Your 2nd for gets roughly translated to:

optRoom.flatMap(room => guys.flatMap(guy => girls.map(girl => s"$guy dances with $girl in $room")))

Since you have optRoom.flatMap(room => ...) it is expected that the parameter is a Function from String => Option[B], but guys.flatMap(...) is not of type Option.

Kigyo
  • 5,398
  • 1
  • 17
  • 21