Hi there :)
I congratulate to the new directon Roc is reflecting in this video.
I think its pretty clear to see, that the syntax improved A LOT, and Roc is on my list of potential contenters to become my main language.
Me and a couple of friends research on concatinative languages to do our own language.
Did Roc consider that as well, as it was originally conceptually?
Do you allow for multiple dispatch?
That would be absolutely game breaking for me :smile:
I never considered concetenative for Roc - feels like it makes the language way harder to learn and the benefit doesn't seem to justify it to me
by multiple dispatch do you mean you can define multiple implementations of a function with the same name, and then the compiler dispatches to one of them based on the type matching?
Richard Feldman said:
I never considered concetenative for Roc - feels like it makes the language way harder to learn and the benefit doesn't seem to justify it to me
Interesting, what do you find harder about it?
Because it is unusual, or some objective reason?
And yes, multiple dispatch as in Julia and Raku.
unusual and especially because it's unusual in an unusual way if that makes sense - like it's unusual for Roc to use -> instead of |> but languages use slightly different sets of operators all the time so it's at least the type of thing people are used to being different between languages
being unusual about how functions get called is pretty much unique to concatenative languages :smile:
multiple dispatch I wouldn't consider because of compiler performance
I don't think it's likely that you can both have that and a fast compiler
the compiler just has to try a bunch of different options in a bunch of different places, no way around doing tons of extra work
Richard Feldman said:
multiple dispatch I wouldn't consider because of compiler performance
Oh, I would have expected that you think it can only be applied with dynamic dispatch, so that argument instead surprised me. :slight_smile:
Well, Raku and Julia both have proper compiler performance, so I don't think its unsolvable.
Obviously, this depends a LOT on how strong the global type inference is, and there are ways to make that performant.
As an argument for it:
It solves the expression problem (almost no language does that, besides dynamically typed ones) and it is the obvious way to perform polymorphism for open source projects.
You cannot extend freely with most other forms of polymorphism, which is desirable for closed source projects.
Which is probably the reason for its absence in popular languages.
About concatenation, I will say that this is an understandable reasoning from a human perspective, and a non-argument from an engineering perspective:
Unusual syntax and semantics can simply mean, we are are used to doing it wrong.
Getting off cigarettes also feels unusual, I don't see how this is an argument against it.
Being compatible with the expectations of people can simply suggest that we repeat the mistakes of the past:
Its compatability to disfunction.
We often think in terms of weirdness budget, something can be unusual/weird if it brings enough benefits and does not make the language too weird overall. If the language is optimal from an engineering perspective but so unusual that basically nobody wants to try it out, we will not have made a meaningful impact on programming. So we want to strike a good balance here.
Anton said:
We often think in terms of weirdness budget, something can be unusual/weird if it brings enough benefits and does not make the language too weird overall. If the language is optimal from an engineering perspective but so unusual that basically nobody wants to try it out, we will not have made a meaningful impact on programming. So we want to strike a good balance here.
That sounds quite reasonable.
Personally, I think multiple dispatch is absolutely perfect under this perspective.
Concatenation is worth a debate, since it can enable extremely potent VM with a few hundred lines of implementation.
That is a fraction of Lua. Meaning you can implement on a range of languages, and you inherit their ecosystem.
Roc has very good properties for systems level programming, and I appreciate that.
I think multiple dispatch would make it similarly potent for higher level applications and concatenation is a very substantial difference to the current design, so integrating it now is seriously a hard choice since it would set back the project very substantially.
ShalokShalom said:
Richard Feldman said:
multiple dispatch I wouldn't consider because of compiler performance
Oh, I would have expected that you think it can only be applied with dynamic dispatch, so that argument instead surprised me. :slight_smile:
Well, Raku and Julia both have proper compiler performance, so I don't think its unsolvable.
it's been a goal from the beginning for Roc to be much faster at both compile time and runtime than Julia or Raku (among many other languages!) :smile:
separately, even if the performance cost were free, I don't think the semantics fit with Roc - e.g. I've separately considered whether it would make sense just from a semantic perspective for Roc to have:
...and my conclusion was that it's best for this language to not even have optional arguments, let alone multi-arity functions, let alone multiple dispatch - and that's even if the performance were free
so to me, I'd say both the semantics and the performance of multiple dispatch are independently deal-breakers for Roc
default valued args ... Still hold a place in my heart.
fwiw nominal records do offer a possibility of reintroducing default-value records
now that the way we ended up constructing them is that anonymous records unify with them
but that's a separate topic :smile:
Richard Feldman said:
separately, even if the performance cost were free, I don't think the semantics fit with Roc - e.g. I've separately considered whether it would make sense just from a semantic perspective for Roc to have:
- optional arguments
- multi-arity functions, which is a more flexible superset of optional arguments
- multiple dispatch, which is a more flexible superset of multi-arity functions
...and my conclusion was that it's best for this language to not even have optional arguments, let alone multi-arity functions, let alone multiple dispatch - and that's even if the performance were free
What's the reasoning behind this?
That sounds as if you are aiming to be a functional systems level language first and foremost, and to compete with Zig, Odin and consorts.
Do you also plan to focus on higher level tasks, that ask for sophisticated polymorphic abstractions, and that like?
Or do you aim to achieve that somehow novel?
And yes, compile time multiple dispatch on types shouldn't introduce much overhead, if anything at all.
JuliaC manages to perform 1:1 on the level of C, so I think being much faster at runtime than Julia will be tricky. ;)
in order for it to be true that a language that maintains dynamic typing information at runtime to be "1:1" with C's performance (when C does not keep that information in memory), one of the following would have to be true:
it makes sense that Julia benchmarks would skew towards arithmetic, since it's focused on use cases like scientific computing, but it would be literally miraculous if Julia were 1:1 at performance with C for use cases like web servers and GUI applications :smile:
regarding optional arguments, multi arity, and multiple dispatch, unless there's some polymorphism mechanism associated with them, they're just ways to avoid naming things differently - e.g. with multiple dispatch you can have two functions both named foo which accept different types, or you can just make one of them named something other than foo at which point it doesn't matter whether you have multiple dispatch
the only two ways it could matter beyond naming are if you're using it for some sort of compile-time polymorphism (at which point you're paying for it in build times) or runtime polymorphism via dynamic typing (at which point you're paying for it in runtime memory usage and branching, plus missed compile-time optimizations, among other costs) so the upsides of that polymorphism had better be worth it!
I've looked at APIs that use all of these features and my conclusion has been that it's better API design to just have functions with different names - and since that also happens to be the fastest at both compile time and runtime, it seems like the obvious choice for Roc!
Richard Feldman said:
I've looked at APIs that use all of these features and my conclusion has been that it's better API design to just have functions with different names - and since that also happens to be the fastest at both compile time and runtime, it seems like the obvious choice for Roc!
Do you think just using functions with different names suddenly solves the expression problem?
I don't think the expression problem is important. It's never been a consideration for Roc's design (and I don't think it should be either)
Last updated: Dec 21 2025 at 12:15 UTC