Hi! I stumbled upon Roc yesterday and immediately fell in love, eve though I have very limited experience with purely functional languages.
I'm trying to work with a string, where separators are ".." and ".", and converting it to a nested list:
"a..b.c" ~> [["a"], ["b", "c"]]
I have written the following in the REPL:
» "a..b.c" |> Str.split ".." |> List.map \item -> Str.split item "."
[["a"], ["b", "c"]] : List (List Str) # as expected
» "a..b.c" |> Str.split ".." |> List.map \item -> Str.split item "." |> List.map \sublist -> Str.joinWith sublist "_"
#expecting output ["a", "b_c"]
This Roc code crashed with: "Erroneous: Expr::Closure"
── TYPE MISMATCH ─────────────
This 2nd argument to |> has an unexpected type:
4│ "a..b.c" |> Str.split ".." |> List.map \item -> Str.split item "." |> List.map \sublist -> Str.joinWith sublist "_"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The argument is an anonymous function of type:
List Str -> Str
But |> needs its 2nd argument to be:
Str -> Str
I understand the issue is that the latest map in my chain receives strings as its input, but based on my experience, I think it should be ["a"] and ["b", "c"], as these are the elements of the list of the previous expression's output. What am I missing?
And just as I pressed send, I have realized the pipe is being considered as part of my first callback :face_palm: Calling it wrapped in parens provides the expected result:
» "a..b.c" |> Str.split ".." |> List.map (\item -> Str.split item ".") |> List.map \sublist -> Str.joinWith sublist "_"
["a", "b_c"] : List Str
Is there a recommended way of using parens? Should a callback be always wrapped?
Usually each part of the pipeline will be on its own line, that fixes it. But if you want it to be on one line, you'll have to use parentheses
This sounds like something that might benefit from a custom compiler error? It sounds easy to detect and might be a common newbie mistake.
I'll make an issue for it
Last updated: Jul 06 2025 at 12:14 UTC