3 ms·
> Appending the exclamation mark will CPS transform that Task value by wrapping it into (possibly nested) calls to `Task.await`, as I understand the article. T
by rtfeldman 2y ago
> Appending the exclamation mark will CPS transform that Task value by wrapping it into (possibly nested) calls to `Task.await`, as I understand the article.
The article briefly mentioned this edge case:
> Since this is the last task in a chain, the ! doesn't do anything and isn't necessary…so we just drop it during desugaring instead of giving a compiler error or generating an unnecessary Task.await. This allows for a more consistent visual style, where async I/O operations always end in the ! suffix, but doesn't have any runtime cost.
That's why it would return a list of Tasks.
- still_grokking 2y agoSo the semantics of this program would change if I added a line containing an exclamation mark somewhere after this expression? That smells like the worst kind of action at a distance… Also, how is the expression `doSomething!` typed then? Does it have different types depending on where it's written? And how do I actually write something `traverse`-like? How to actually write list.forEach (lambda f => readFile! f) than, if I really want the effect to run inside the lambda body?
- mrkeen 2y ago> I also don't get how running ... would result in a list of Tasks That's the contract of 'map' in any FP. Turn a container of A into a container of B, and do nothing else (in this case - no telling tasks to start executing). > Appending the exclamation mark will CPS transform that Task value ... is problematic as you need to also CPS transform the lambda You may be overthinking it. I believe (!) is a syntax-only transformation which happens very early in the compiler pipeline. And I don't think you need to invoke CPS here: CPS From [https://matt.might.net/articles/cps-conversion/] The M function only has to watch for lambda terms. When it sees a lambda term, it adds a fresh continuation parameter, $k, and then transforms the body of the lambda term into continuation passing style, asking it to invoke $k on the result. Variables are unchanged In Roc (and Haskell, Scala, Idris, ...) you don't need to generate a fresh $k under the hood, because it's already right there in the surface language (in this case, foo): foo = mytask! "abc" is already equivalent to: mytask "abc" (\foo -> ... ) > See for example CPS-async in Scala: Why didn't you mention Scala earlier :D. This is the same trick as Scala for-comprehensions. Here's an example in that repo: https://github.com/rssh/dotty-cps-async/blob/36f2e3b61542b39436267aa4cd911576a5a15247/shared/src/main/scala/cps/macros/forest/CpsTree.scala#L640 https://github.com/rssh/dotty-cps-async/blob/36f2e3b61542b39... > Also every higher order function would need to be there in two variants. Literally every HOF? Nah, but you're right that there is duplication - and there needs to be, since there is a distinction between: convert a *list of filenames* (input) into a *list of Tasks* (output) which will read those filenames convert a *list of filenames* into Tasks which will read those filenames, and return their *contents* (output) If you have List and Task modules, then "do this List of Tasks" obviously has to live in List's source code or Task's source code. It's an N*M implementations problem, but fuck it. Computers do Lists of Tasks so it's worth implementing. Haskell does a little better non the non-duplication front. By going down the typeclass/monad route, you can put the "do this List of Monads" in List.hs, and "Task is a Monad" in Task.hs, and you're all set. But it still makes a distinction between 'map the list' and 'map the list and return the results of running the monads inside it'. It calls them map and mapM respectively, and also has mapM_ which carries out the effects but also ignores the output. Anyway, back to my Java day job where the duplication issue in the stdlib is solved by just ... leaving out functionality. Let's see how we tackle the List of Tasks issue: https://stackoverflow.com/questions/30025428/convert-from-listcompletablefuture-to-completablefuturelist https://stackoverflow.com/questions/30025428/convert-from-li...