Stream: ideas

Topic: Exploring function calls


view this post on Zulip Sebastian Fischer (Nov 25 2021 at 15:58):

Inspired by the recent discussion about backpassing, I wrote a Gist exploring different ways of calling functions. It helped me get a clearer picture of the pipe operator and backpassing, and I'd be glad if it can help others too!

I'd also be interested in further thoughts you have on the topic.

view this post on Zulip Richard Feldman (Nov 25 2021 at 19:36):

that all looks accurate to me! :100:

view this post on Zulip Richard Feldman (Nov 25 2021 at 19:36):

btw regarding this:

At the time of this writing, executing callbackPipe2 leads to a run-time error, but executing the original callbackPipe does not.

would you mind opening an issue for that? :smiley:

view this post on Zulip Sebastian Fischer (Nov 25 2021 at 19:37):

Will do!

view this post on Zulip Sebastian Fischer (Nov 26 2021 at 12:16):

I removed the footnote because the error had nothing to do with callbackPipe2, just with combining the results of the different definitions. I created a new issue with a minimal example program.

view this post on Zulip Richard Feldman (Nov 26 2021 at 12:24):

awesome, thank you!

view this post on Zulip Míla Kuchta (Jan 05 2023 at 07:36):

Hi guys, regarding function definition vs function calls I think it not very symetric (and can be confusing) that functions parameters are separated by comma, but called without comma...

view this post on Zulip Brendan Hansknecht (Jan 06 2023 at 00:52):

This is definitely something you get used to pretty quick, but I definitely can see the want for it to be symmetric.

I think the current trade off is kind of (maybe not totally intentionally) built to avoid extra parenthesis and aid in readability.

If you remove the commas from a type definition, you have to add parens around complex types
base:

func: \List U8, T Nat Str, Str -> U8

would be:

func: \(List U8) (T Nat Str) Str -> U8

I think this second example is very strange to read.

If on the other hand, you add commas to calling a functions, it requires extra parens, can be confused with tuple and record syntax, and looks really strange with pipeling.
base:

x =
    Str.joinWith ["test", "one", "2", "three"] ", "
    |> Str.concat "\n some new line"

y = {
        val1: Num.addWrap 3 7,
        val2: SomeTupleFunc (3, 4, 5) "test",
        val3: (List.repeat 0 8, x),
    }

would become:

x =
    Str.joinWith(["test", "one", "2", "three"], ", ")
    |> Str.concat("\n some new line") # This really feels like Str.concat takes only 1 param

y = {
        val1: Num.addWrap(3, 7),
        val2: SomeTupleFunc((3, 4, 5), "test"),
        val3: (List.repeat(0, 8), x),
    }

Of course you could still do this without paren, but that is also strange:

x =
    Str.joinWith ["test", "one", "2", "three"], ", "
    |> Str.concat "\n some new line"

y = {
        val1: Num.addWrap 3, 7, # Should a third param go here or is this the next record field
        val2: SomeTupleFunc (3, 4, 5), "test",
        val3: (List.repeat 0, 8, x), # Does List.repeat take 1, 2, or 3 params. No clear way to tell.
    }

Note: tuple syntax is not in the language yet, but is a planned feature.

view this post on Zulip Joshua Warner (Jan 06 2023 at 03:03):

FWIW I don't currently love the space-delimited call syntax, and I think I'd actually prefer if the syntax were the same as rust/java/c/etc function calls - funcName(arg1, arg2, arg3). Maybe it'll grow on me some day. I think having commas on the def side but not on the call side does make it particularly awkward.

view this post on Zulip Míla Kuchta (Jan 06 2023 at 14:46):

Spaces for applying functions work well for the curried languages (from which ROC borrow it's historical origins) but don't have that much sense for the uncuried ones and is much harder to grasp for users of mainstream languages. I would be quite cautious when mixing different ideas from different language families since having simple consistent syntax is very important for new users to immediately get a language and not to run away searching for the other one in abundant space of new languages. I think Koka (from which ROC borrowed some implementation ideas - Perceus Reference Counting etc.) get that very well...

view this post on Zulip Míla Kuchta (Jan 06 2023 at 15:35):

On the other hand, I understand that if ROC tries to be also good shell language that breaking that convention is very hard. I've spent a lot of time thinking how to make the best universal syntax for both of these worlds of programming and shell scripting and it's very hard to come up with something that is simple and consistent...

view this post on Zulip Míla Kuchta (Jan 06 2023 at 15:48):

Advantage of the parrens for separating complex inner expressions are that they are needed just in case there is complex inner expresion and not all the time but it's harder to make such simple consitent rule for separators (as opposed to wrappers)...

view this post on Zulip Brendan Hansknecht (Jan 06 2023 at 15:53):

As a note, i am not sold to the current syntax or saying it should stick around. Just noting why I think it currently is in the form it is.

Personally, I think it would be a great idea to remove the commas from type definitions and function definition. I just don't know how to do that in a way that doesn't lose readability.

On the other hand, after writing a significant amount of roc, i definitely do not want commas in functions calls or a regular c style call syntax.

view this post on Zulip Brendan Hansknecht (Jan 06 2023 at 16:03):

Related aside, i think i figured out why I dislike this syntax:

func: \(List U8) (T Nat Str) Str -> U8

Even though it isn't possible in roc, i want to read the input as one type somehow. Either like some sort of higher kinded type where (List U8) would be a type that takes two other types as type variables. Similar to writing:

func: \Dict (T Nat Str) Str -> U8

This second example is valid but is only one input type. It is a function that takes a dictionary with a key of T Nat Strand value of Str. The function returns a U8.

Otherwise, i kinda want to read it as a type level function. List is a function that takes U8. It then returns a function that takes (T Nat Str) Str to define the final input type.

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:08):

Yes, I totally understand that, I personally very much like the idea to have a space separated call syntax so that it's compatible with the shell (where most beginner programmers used to start (I don't know how it is today though :)) But space separated call syntax and space separated type parametrization syntax is probably too much :). Regarding that type parametrization is something totally different than function application, maybe separating those two syntaxes makes more sense...

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:12):

And it would still make a great shell language, since when using the shell, you mostly just call things but don't that often define new things (where you would use types or constructors)

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:27):

Because if you don't strictly limit the use of space separated syntax for evaluation of some kind, it would be very hard for newcommers to know where to stop following that rule and don't get lost in mental evaluation :)

view this post on Zulip Joshua Warner (Jan 06 2023 at 16:40):

IMO trying to be both a good shell language and a good general purpose language is basically impossible.

view this post on Zulip Joshua Warner (Jan 06 2023 at 16:41):

I think there’s fundamental incompatibility there

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:44):

I don't think it's impossible, if you take e.g. haskell it's quite compatible with the shell syntax...

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:46):

But even a good shell language don't have to follow the current convetions, sometimes convetions must be broken to make some progress happen...

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:51):

It's just that shell syntax must be concise and simple enough (without much use of puntuation etc), so that non-programmers wouldn't be scared of it :)

view this post on Zulip Míla Kuchta (Jan 06 2023 at 16:56):

At least for usual stuff like executing a program or calling a function (which should definitely look the same for them (at least in some shell sublanguage), so that they don't have to think about the difference)


Last updated: Jun 16 2026 at 16:19 UTC