No, there isn't. There is a ticket though: https://issues.scala-lang.org/browse/SI-2823
Is there a way to declare an implicit val inside a for comprehension?
-
13-12-2021 - |
Frage
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
.
Lösung
Andere Tipps
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*