When I have a function that takes a while (not because of IO or whatever, just computation), is it possible to output something to the console when that function runs? I know about "dbg", but that doesn't do anything when running the binary, only when running "roc dev".
Something like this:
processRange: Nat, Nat -> Nat
processRange = \start, length ->
Stdout.line "Processing range: \(start) - \(start+length-1)"
somethingThatTakesLongToCompute start length
I haven't been able to find any syntax that makes Stdout.line work in a function other than main, maybe it's not possible? Am I doing this wrong? There should be some way to indicate to the user that the program is still running, just working on whatever task it's been given, right?
We want debug to work in this case...It just doesn't currently.
For Stdout.line
to work in an arbitrary function, that function would need to be changed to return a Task
Then you would need to await that task
It is a solid bit of extra juggling
specifically, you could do something like this
processRange: Nat, Nat -> Task Nat *
processRange = \start, length ->
{} <- Stdout.line "Processing range: \(start |> Num.toStr) - \(start + length - 1 |> Num.toStr)" |> Task.await
somethingThatTakesLongToCompute start length |> Task.ok
Then you also have to change the caller to await the returned task
Yes, that would be some extra juggling since there is really no other need to change the type of that function than to be able to report progress to a user waiting for the result. It would just be nice to be able to provide an ETA or some indication that something is still happening while long computations run.
For example, right now I'm running something that might take minutes, hours or days and I have no idea which unless I can see some progress. In "roc dev" it will take days, for sure, but --optimize speeds things up a lot so it may be only hours in that case but I have no way of knowing.
I'll try and see if I can type-juggle that Task into the function. What I'm doing is probably wrong since I didn't expect it to take anywhere near this long, I was hoping for seconds.
I would break the input into chunks and print an update after each chunk is processed.
So now I have a List (Task Nat *)
that I'd like to each await, get the result and do something with the resulting list of results. I'm trying to List.map
using Task.await
and I'm not getting anywhere. Probably because that's not how things are done in Roc.
main =
ranges
|> List.map \range -> searchRange range
|> List.map \task -> await task ???
|> List.min
|> Task.ok
searchRange : Range -> Task Nat *
searchRange = range ->
{} <- (Stdout.line "Searching range \(Num.toStr range.start) \(Num.toStr range.length)") |> await
somethingThatTakesALongTime range |> Task.ok
Is it possible to wrap the awaiting of a bunch of tasks into another task that can then process the results of each of the smaller tasks?
You need something like https://www.roc-lang.org/packages/basic-cli/Task#loop
Took me a while and I had to sprinkle await
and Task.ok
everywhere until it compiled, but I finally did manage to get it working with Task.loop, thanks! It's still taking way too long, but that's just because my implementation is slow. I did manage to print status updates while the computation is running.
Last updated: Jul 05 2025 at 12:14 UTC