I see that you say foo.map(x => x.bind)
will work, but it’s not clear to me how your proposa allows that to happen.
- Will it work for every higher-order function?
- Do the HOFs need to be specifically annotated for them to work?
- What about HOF’s defined earlier and already compiled?
- What about HOF’s defined in Java? Or Javascript for Scala.js?
The interaction with HOFs has been the achilles heel of every async/cps transformation I’ve seen. While languages have a finite set of features that you can hard-code support for, the variation in user-defined HOFs are limitless. Even the same HOF can have diffeerent interpretations: e.g.if I call listOfItems.map(item => Future(doThing(item)).bind)
, how does the compiler know if the user wants the doThing
calls to happen async-sequentially or async-concurrently?
Different implementations taking different approaches, e.g. the old Scala-CPS plugin required HOFs to be compiled with a specific annotation IIRC, while scala-async doesn’t support HOFs at all. The same issues even apply to other languages, with Kotlin’s suspend functions, C# async, Python async, JS async all having different approaches to HOFs
HOFs are much more common in Scala than in any other language, and even are used for what in other languages are typically baked-in language features: loops, context managers, try-with-resource, etc. This problem which is a edge-case in other languages is a core problem front-and-center in Scala. This proposal needs more clarity on how it approaches HOFs: how it works, what works, what doesn’t, and what tradeoffs it chooses to make around them.