I am a seasoned Clojure dev, and I have just finished reading the entire roc tutorial. I haven't written a single line yet, but I have (somewhat carefully) read & understood all the examples. So at first glance, I am seeing a typed lisp (of sorts). I mean for starters, it is expression-based, nesting happens with parentheses (although the most outer/inner ones can be omitted), function invocation uses prefix-notation (even infix arithmetic expressions are de-sugared to prefix), bindings are immutable etc etc. So I am naturally wondering, why not admit your core-identity and/or heritage? What is this pathological fear of being labelled a lisp? In any case, the language itself looks super interesting - I can't wait to start playing with it. :)
No fear just not really our direct lineage
We come from elm
elm comes from other ml languages
other ml languages maybe come from lisp
idk
Also, without the macro system and more code is data style, I feel like we are missing the core of what makes a lisp
Yes exactly - I was more meaning syntax-wise :)
Would you still call it lisp like when we still have regular math and comparison expressions? So not everything is parens based. Just function calling is lisp like I guess.
but that is also exactly the conundrum I'm having right now...if your source code is already nested lists, then you get the macro-system basically for free (over-simplifying here). I haven't seen enough roc code to claim that it is all nested lists, but that's the impression the tutorial gave me. I was particularly convinced when I read the section about de-sugaring arithmetic operations...
the 'regular' math comaprison stuff is all sugar no?
anyway, I'm not trying to make a serious argument here - I was just pleasantly surprised to find the tutorial so accessible coming from Clojure.
I'm not trying to make a serious argument here
I know
the 'regular' math comaprison stuff is all sugar no?
Sure, but that is really just semantics. every operations is a function. functions takes arguments.
But I guess if someone wanted, they could write everything in nested parens `Num.add (Num.mul a b) c)
We also really dislike linked lists. (myself more than others, but in general overall we discourage them)
Aside, how do things like when ... is
pattern matching fit into a lisp?
well that's easy - just wrap the whole thing in parens and drop the is
:stuck_out_tongue: jokes aside, that's exactly how my brain first parsed it - as a plain switch-style expression
i'm not sure if it's coming across, but I'm saying all these things as positives
@Dimitrios Piliouras
This was nice to read! Lisp was where I started with programming, and always has felt like home, but Elm and Roc's focus on short development cycles has grabbed my attention these last few years. You may be interested to know that, while LISPy macros probably won't find a home in either language, there are code-generation tools that have a lot of nice ergonomics thanks to the language designs here: https://github.com/mdgriffith/elm-codegen/blob/main/guide/WritingAGenerator.md
I'm not finding a good link for it, but another LISP-like feature of Roc is that a program can have a nice compilation-step free development cycle if you ask the compiler to run your code ignoring errors. To me that resembles the interpreted or compiled nature of a Common Lisp experience
@Drew Lazzeri thanks for the link...I have to admit that Elm does look pretty interesting, however generating code as Strings doesn't really impress me, as It can get hairy really quick...also, this idea of 'running your code ignoring errors', sounds new to me, so I would be interested to find out more. I mean, how is this even possible, and perhaps more importantly, how is it useful? When I run my programs, I am always interested in potential errors...
@Dimitrios Piliouras When you are in the middle of changing something and you just want to test out your change for the path you have written. Maybe you have written a pretty complex algorithm that gets run in one of the branches of your program and you are curios if you have done it correctly. In the other branch paths, your code is still the older version that produce a different type. You could just comment out the other branch bodies and insert a crash "not yet implemented"
into each of them, but the current roc run
command comes for the rescue. The compiler inserts a crash into the program whenever it encounters an error when you typeroc run
. I always imagine these crash messages being smting like "I told you I would crash, but you just wanted to see it yourself."
oh I see - yeah that's pretty neat :)
Last updated: Jul 06 2025 at 12:14 UTC