-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow using async in for loops over collections #32
Comments
This sort of change means that async needs to have special knowledge of collections to undo the translation of for-comprehensions. An alternative is to use a macro inside the async block: async {
foreachMacro(xs) { x =>
await(f(x)
}
} where I guess the problem with adding special cases like this to async is figuring out where to stop. It would also be nice to write: So we need to give this one a bit of thought. Right now, our top priorities are fixing a few outstanding bugs, and adding support for await in try/catch. /cc @phaller |
I see, that makes a lot of sense. What about using typeclasses to distinguish safely traversable/mappable/... entities? One way would be to embed this functionality into |
+1 for typeclasses for traverse. A big group of higher order functions are of the form f(x: M[A], t: A => B): M[B], including all the collections operations, Option, Future, Try, and many others. Providing an implicit |
@pelotom has done a similar job with Scalaz in his "idiom bracket" inspired applicative macro, https://github.com/pelotom/effectful That needs to be layered on top of scalaz (for I do encourage more experimentation in this area. As I mentioned about, you could compose two macros manually: async { rewriteMapWithTraverse {
}
} If you like the result, you can make a macro that calls the other two: myAsync {
} |
Having started playing with this library for reals now, here's another useful 90% solution for the "await inside for loop" problem async {
for (x <- xs) {
doStuff(awaitOnce(otherThing))
}
} being translated into async {
val $fresh = await(otherThing)
for (x <- xs) {
doStuff($fresh)
}
} It's not a perfect solution, but I feel it'd hit the 90% use case of |
@lihaoyi I respectfully disagree :) Why would you put |
Yeah, it's not a 100% solution, but I feel it'll satisfy some of the need. FWIW I have just discovered that this works really nicely: import scala.async.Async._
import scalaxy.loops._
async{
for(y <- 0 until canvas.height optimized){
await(Future())
}
} Who'd have thunk it? I'm using it to great effect in some of my code, and it works exactly as you think it would: from for-loop to while-loop to tail-recursive-async-function. |
@lihaoyi Interesting! That’s an option for sure. P.S. Do you mean “who’d have thought it?”, or it’s a pun on a well-known programming concept? :) |
I suspect in general, stream-fusion macros would be able to satisfy a pretty large set of use cases. e.g. scalaxy-streams inlines { Now if only there was a stream-fusion library that was solid enough to depend upon. Between scalablitz, scalaxy-streams, and speed, we have no shortage of experimental implementations! |
Most (all?) of those libraries use |
Yeah, but I'd consider that an implementation detail. I think the approach is pretty reasonable: it's not quite as "general" as a monadic-traverse based implementation, since it's basically hard-coding a bunch of special cases, but the fact that we can share these hardcoded-special-cases with the people who do it for the performance it makes it less-bad. Again, none of the libraries I've linked are anywhere near production quality, so we're not there yet =) |
I think this feature does not require any changing in I have implemented such a I hope this approach would be helpful. |
Scala-gopher apparently uses async with some additional macros to allow it to work inside for loops:
Maybe this could be generalized and included in scala-async itself? |
As everybody may know, following code:
is translated by compiler to:
So in order to support
where signature of
To achieve this, we may use implicit conversion:
then provide implicit conversion helper to convert them to
When ever we see |
Hi,
I think in case of (sequential) collections this code
could be rewritten into
thus relaxing the restriction regarding
async
inside closures. It only saves a few lines, but looks more idiomatic. What do you think?The text was updated successfully, but these errors were encountered: