Hey folks - I was parsing through the topics to familiarize myself with recent changes and came around the static dispatch homepage changes thread.
Are all those changes confirmed? I'm just starting out a webserver built with Roc and I got a lil bit concerned if I would need to rewrite and relearn everything in a few weeks/months.
I'm withholding judgment on the actual changes as my rubber ducking discussions usually makes me understand and relate to their goal (static dispatch demanded a lot from me as an Elm developer but I think I get the advantages now, though framing the change motivation as "its more familiar" is the wrong approach imo)
Expanding on this topic - after reading more about dynamic dispatch, the new lambda syntax, and the related inline type definitions, I just worry the end result accumulates:
I still quite think of Roc as "Elm in all domains" as recently talked about @Richard Feldman in a podcast. Though I can understand that to give the same _feeling_ of Elm it might need to look vastly different since the constraints are so different as well. So I'm personally biased towards trusting all decisions made that diverges Roc from Elm on a superficial level.
My concern lies in losing that same simplicity and joyfulness while exploring multiple parallel ideas. I can see that this is something easier to explore/test than prematurely discussed.
But just as a data point: I think Gleam followed similar paths (parens, inline type defs, ..) with the goal of being more approachable and it worked! But I actually use Gleam in production and I have to say - it is vastly different from Elm even though the footprint of both languages are similar. This is obviously my personal opinion, but I just don't feel the same "joy" as I do with Elm.
This joy is, imo, what makes a group of super intelligent people to keep working on their tools for Elm to this day, even when the language clearly lost mainstream interest, so I think there is a value to be seen and appreciated that is not seen in many other languages.
How much of the joy do you think comes from elm's dialled in framework for a single domain vs from the actual syntax?
And yeah, the fundamental feel of the language is definitely changing. Mostly with parens call syntax and static dispatch which enables it.
Inline annotations are just at the idea stage and not accepted/planned.
New lambda syntax seems to be accepted at this point. Not guaranteed, but it seems to fit really well with parens calling syntax
Fundamentally, roc is shifting more imperative.
thanks for sharing this, I really appreciate hearing it! :smiley:
so the thing that I initially loved about Elm was not the syntax (I already knew about the syntax from Haskell, and I felt comfortable with it but it wasn't what drew me to the language) but rather these things more than anything else:
since Roc's first commit in 2019, here a comprehensive list of major changes to the APIs:
-> Task a b
to => Result a b
that's it, there haven't been any others :big_smile:
so to me, one of the main things that makes Roc feel like an Elm-like language - namely, the simple APIs based around pure functions - is still almost completely the same
here is an excerpt from roc-for-elm-programmers.md
from 2019 (fun fact: this document was the original Roc tutorial; I figured it would be faster to start with "these are the ways Roc is different from Elm" than a whole tutorial for people who hadn't used either language!)
toInt : [ Foo, Bar Str ] -> Int toInt = \tag -> case tag when Foo -> 1 Bar str -> Str.len str
today, this would be:
to_int : [Foo, Bar Str] -> U64
to_int = \tag ->
when tag is
Foo -> 1
Bar str -> Str.count_utf8_bytes str
with the current set of design proposals, this would become:
to_int : [Foo, Bar Str] -> U64
to_int = |tag|
when tag is
Foo -> 1
Bar str -> str.count_utf8_bytes()
I bring up this example because in all the proposals we always focus on code examples that would be affected by the proposal (because what would be the point of spending time discussing "this part wouldn't change?")
but I've been working on a realworld back-end example in Roc (it's still WIP, not ready to publish yet) which uses all the currently-accepted design proposals, and one of the most striking things to me is that all the code still feels structurally the same as ever
yeah some of the expressions look different, but I bring up this example snippet because the changes from 2019 are so minimal:
[
and ]
in the formattercase ... when
became when ... is
toInt
became to_int
by overwhelming popular request\tag ->
became |tag|
Str.len str
became Str.count_utf8_bytes str
and then str.count_utf8_bytes()
the structure is the same, the types are the same, it's still pure, the compiler knows it's pure, and each line does the same thing as it did in 2019
this is true of a lot of Roc code :big_smile:
so I understand the concern about some things looking different, but honestly I think the biggest thing that makes Roc nice to use is the structure of the programs - how things fit together, purity being first-class, the APIs being designed around purity and semantic immutability, etc.
and the structure of Roc programs is still the same as it always has been; actually the biggest change there has been module params (which I know aren't used much in the wild today, but they are used a lot in the realworld code base!)
I also realize the past year has had an unusually high number of design changes that affect syntax compared to previous years - 12 months ago, all I/O was done with backpassing and Task
, and in the span of one year we got the !
suffix and then changed to !
being part of the function's name, along with purity inference...it's a lot in one year!
I think it's fair to look at Roc getting return
and (in the future) for
and var
and conclude that it's getting more imperative, but the function types don't change at all because of this. I think that's what is really critical to the essence of the language! Yes, it does permit writing pure functions in a more imperative style, but honestly I've really enjoyed the ability to do that so far.
It turns out I find some pure functions genuinely nicer to read when implemented in an imperative style. This is not something I knew based on my experience with Elm, but I'm really glad we tried it! :smiley:
my experience with writing static dispatch code so far is that it doesn't actually feel that different in terms of the things I'm thinking about. I'm still mostly focused on "what are the types of these functions, how do they fit together, how do I avoid =>
if I can reasonably get away with ->
, and then finally, how do I implement the function to satisfy all that?"
and that last piece feels different, but it still mostly feels like a 1-to-1 translation of what I would have written before static dispatch :big_smile:
honestly, one of the most surprising things about spending time with this style has been realizing how little it affects the way the code is put together
there's very little "hm...how do I change my code to work with static dispatch" and a lot of "ok, time to a bunch of mechanical 1-for-1 changes. Oh neat, now this fits nicely on one line!"
so I predict that if you like Roc today, you'll like it in the static dispatch world too. That's certainly been my experience so far! :smiley:
First of all, thanks a lot for the careful response!
I wholeheartedly agree that one of Elm's strongest points is how stable it has been for the last 5 years or more. That allowed a lot of tooling to be built around it. Tools that were counting on its stable APIs.
I was looking for a summary like the one you gave just now to understand last year's changes! Like I said, I've been optimistic about all the changes I've seen so far even when I had a confused first impression - Roc's domain is so different from Elm, it makes a lot of sense that it needs different solutions.
I'd argue that being a small language with little-to-no hidden features or syntax sugars is also a feature of Elm that allows teaching someone easily and explaining that "everything else is built on top of these set of things, no magic".
I started to create a webserver using Roc just yesterday so thanks for sharing your repo - even in a work-in-progress state it will be immensely helpful for me!
To sum things up - thanks for the summary of changes, I continue to be optimistic that Roc might be just ambitious enough to actually achieve something I've been trying to find in other domains. I just hope that the development process can accommodate frequent pauses to consider the big picture and how these individual, well meaning, experiments can create a cohesive whole with a minimal set of implicitness and "magic".
I just hope that the development process can accommodate frequent pauses to consider the big picture and how these individual, well meaning, experiments can create a cohesive whole with a minimal set of implicitness and "magic".
That's one of the main principles I and a lot of the other contributors are trying to approach Roc's design from! We really value that trait in Elm, and try to preserve it. I think some of the complexity seen comes from Roc trying to be a general purpose language instead of just a SPA DSL, but it's totally possible and highly desirable to Keep It Simple, Stupid.
I’ve only just started having a look at Roc, having only watched a talk or two a while back but I do like what I’ve seen of the design decisions so far. Ideally i would like a language that is ‘safe by default’ (with regard to memory, mutability and purity) but where i can eject out of that where needed (to eg write an imperitive style algorithm) but these be at arms reach so they aren’t the default. The purity inference / binary algebraic effects with the ! Naming convention together with the for and var changes look to be really pragmatic choices that I’m looking forward to explore and the Algol/C brackets style is realistically a good choice for attracting more people to the language. (As Reason found, syntax matters). The lambda syntax change looks on first impression a bit confusing but i havent read anything about it yet (other than this thread). Is there anwhere i can read more about the static dispatch proposal/change as this is the first time I’ve seen anything on that too? Thanks
Hi @Yunti, you can read all about it here: https://docs.google.com/document/d/1OUd0f4PQjH8jb6i1vEJ5DOnfpVBJbGTjnCakpXAYeT8/edit?tab=t.0#heading=h.vuo6e14bvfkt
Last updated: Jul 06 2025 at 12:14 UTC