This works:
args = Arg.list!
arg =
List.get args 1
|> Result.withDefault "No command line args provided."
But this doesn't:
arg =
Arg.list!
|> List.get args 1
|> Result.withDefault "No command line args provided."
I personally think this would be very handy and I believe users would also expect this to work.
It seems feasible to make the desugaring smarter/adaptive so that this does work.
I'd love to hear your thoughts :)
oh yeah it’s supposed to work! I think it may just not have been implemented yet :big_smile:
It should be working I think, I would expect it to desugar to the same as
arg =
Task.await Arg.list \answer ->
answer
|> List.get args 1
|> Result.withDefault "No command line args provided."
The following works as expected
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
import pf.Arg
import pf.Task exposing [Task]
main =
arg =
(Arg.list!)
|> List.get 1
|> Result.withDefault "No command line args provided."
Stdout.line arg
So there are two interesting things here
! to continue parsing the expression. @Joshua WarnerRequiring indentation there seems wrong… or at least unnecessary
Probably just requires a little fiddling with min_indent
also works
arg = (Arg.list!)
|> List.get 1
|> Result.withDefault "No command line args provided."
doesn't work but fails with a different error
arg = Arg.list!
|> List.get 1
|> Result.withDefault "No command line args provided."
This 1st argument to this function has an unexpected type:
8│> arg = Arg.list!
9│> |> List.get 1
10│> |> Result.withDefault "No command line args provided."
This withDefault call produces:
Str
But this function needs its 1st argument to be:
InternalTask.Task a b
Looks like the same logic as in Luke's snippets above
Luke Boswell said:
So there are two interesting things here
- We need the Parens to unwrap it before passing into the pipeline... maybe this is not the desired behaviour and we should fix that? Richard Feldman
- The parser requires the indentation after the
!to continue parsing the expression. Joshua Warner
Yeah, we shouldn't need the parens or the indentation! :smiley:
May I take this issue? @Luke Boswell would be happy to have some guidance here. I'm struggling with debugging and not sure when exactly it fails - it must be during desugaring of either pizza or task_await, or maybe it's even upstream. Any tips?
Thanks for helping out @Kiryl Dziamura, I've assigned you to the issue :)
@Kiryl Dziamura I'd be interested in pairing to show you what I know about the parser and canonicalisation.
I think an evening my time would probably be best. The earliest I could do is , would that work for you?
Also happy to point to files before then if your keen to get started. :grinning:
It would be great! I'll prepare some questions about the codebase then. Added to my calendar
Also happy to point to files before then if your keen to get started
yes please, I'll do a little digging :)
Curious if you ended up getting any further / figuring it out?
So there are at least two problems:
indentation during parsing: it expects
a!
|> b
instead of
a!
|> b
And then desugaring: it transforms
a = b! |> c
d a
into
a = Task.await x -> c x
d a
instead of
Task.await x ->
a = c x
d a
Upd: I was investigating top level declarations, which is not applicable here.
I expected suffix doesn’t affect indentation at all. Why a specific indentation rule was introduced?
Probably it's caused by the fact that the exclamation mark works both for a task value and functions that return a task value:
a! --> Task.await a x -> x
a! b --> Task.await (a b) x -> x
I wonder if this might only be a parser problem. The |> operator gets completely desugared beforehand.
Might be! I’ll take a closer look today
It's BinOps of Pizzas where the first item is TaskAwaitBang after parsing. So likely it's desugaring
From what I understand, currently, it works this way:
a! |> b -> b a! -> Task.await (b a) \...
The second transformation is incorrect. But b (a!) works as expected, which explains why parens helped in the Luke’s snippet above
The fix for the bang in args (consequently for the pipe logic) is ready
https://github.com/roc-lang/roc/pull/6777
The second part would be for indentation but I’m not sure what’s the current convention. From what I saw in the code, it intentionally expects +1 indentation here. However, it's not clear to me why the bang requires any changes to indentation at all
Last updated: Jun 16 2026 at 16:19 UTC