Question

I have some code with nested calls to flatMap like so:

foo.flatMap(implicit f => bar(123).flatMap(b =>
  /* and so on... implicit f is still in scope here.*/
))

Normally, one would write that as a for comprehension, which makes the code a lot more readable:

for {
  f <- foo
  b <- bar(123)
  /* yet more method calls that need f as an implicit parameter*/
}

But I need f to be implicit and I don't see a way to do that with for comprehensions. Is there? Of course I could pass f explicitly, but that would mean bye bye pretty DSL. I'd be interested in answers for both Scala 2.9 and 2.10.

Just to be clear, I would like to do something like this, but it won't compile:

for {
  implicit f <- foo
  b <- bar(123) //bar takes implicit argument
  /* yet more method calls that need f as an implicit parameter*/
}

EDIT: Maybe a feature request would be a good idea?

EDIT2: This should work with all types that can be used in a for comprehension, so not just with the usual collection types like List or Seq, but also with Future.

Was it helpful?

Solution

No, there isn't. There is a ticket though: https://issues.scala-lang.org/browse/SI-2823

OTHER TIPS

Since version 0.3.0-M1, a better-monadic-for compiler plugin provides such functionality.

Scala 3 (Dotty) enables givens (implicits) in for-comprehensions, for example

Starting dotty REPL...
scala> for {
     |   given _: Int <- Some(41)
     |   y <- Some(1)
     | } yield summon[Int] + y
val res0: Option[Int] = Some(42)

According to Implicits in for comprehensions/pattern matches SIP tracking #6

Martin points out that it Dotty already supports the more ambitious version as long as the types are annotated. so e.g. in Dotty this compiles: implicit val (a: Int, b: String) = (3, "foo")

How about this code?

// prerequisites
val (a,b) = (List(1,2,3), List(3,4,5,7,9))
def tree(n: Int)(implicit s: Int) = " "*s + "0"*n + (if (s+3 < n) "*" else "")

// actual for
@volatile implicit var s = 0
for (i <- a if ({s = i; true}); j <- b) 
  println(tree(j))

// 000
// 0000
// 00000*
// 0000000*
// 000000000*
//  000
//  0000
//  00000
//  0000000*
//  000000000*
//   000
//   0000
//   00000
//   0000000*
//   000000000*
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top