Reputation: 42037
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
.
Upvotes: 38
Views: 6725
Reputation: 48400
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")
Upvotes: 7
Reputation: 131
Since version 0.3.0-M1, a better-monadic-for compiler plugin provides such functionality.
Upvotes: 13
Reputation: 42037
No, there isn't. There is a ticket though: https://issues.scala-lang.org/browse/SI-2823
Upvotes: 19
Reputation: 1703
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*
Upvotes: 0