Being in the Lisp family, an often heard criticism is its use of parenthesis (disclaimer: I understand the difference between syntax & semantics. But syntax does matter).
Racket is s-expression based, so it has a lot of parentheses. Racket can claim to have slightly fewer parentheses than most other Lisps because it uses brackets in some places rather than parentheses.[1]
Rhombus is a novel notation (that is implemented as a Racket macro) which eliminates the need for almost all parentheses. They have a handful of code snippets on their homepage.
I was not very involved in this. I still prefer s-expressions.
Anyway, my main initial concern was how to make good macros without s-expressions. There is a nice video by Matthew Flatt in RacketCon 2023. The first 6 minutes and 20 seconds are internal stuff, so skip to the 380s that I added in this link: https://www.youtube.com/watch?v=OLgEL4esYU0&t=380s He takes like another 6 minutes to explain the general idea and make some wishes, and then at the 12m mark he defines macros in Rhombus and makes the wish real in just 2m (with some enhancements later).
I mean, M-expression was proposed right from the start.
Then there is nothing special about having the brackets around. To start with, text can be just as readable:
( + 1 2 )
do plus 1 2 go
And one can use stack base syntax, or define a static default arity to infix notation, example two, so `times plus 1 2 3` is not ambiguous and is really clearly like (1+2)*3 with such a convention. Then you can shift arity with reserved word so `unary plus 1` is like `+1` or `arity 5 action one two three four`, or going back to explicit marker like `(` and `)` or `do` and `go` to group stuffs without explicitly quantified numbering.
I think my favorite thing is the `…` operator. Go check it out. It’s not like the splat operator in other languages, though it does give that feel initially. It’s much more general: it works with nested data structures and can take the place of a `map` operation.
The best part of `…` is that it is not a built-in thing—it’s just a macro! The magic is that Rhombus lets you define different macros depending on whether or not the macro identifier appears in binding context (left side of `=`), expression context, or some other contexts. IIRC you can even define your own contexts too.
Rhombus takes the best-in-class macro system of Racket and somehow finds a way to improve upon it. I say this after researching and comparing detailed metaprogramming features across a dozen different languages. Rhombus is a very neat little language.
Last thing: Rhombus’ main data type, the list, is implemented with an RRB tree. RRB trees support structural sharing, functional updates, and have O(log n) iterate, insert, delete, append, and arbitrary read operations. The constant factor on that is tiny: I think it’s like log_16 or log_32. They’re designed to be very cache friendly. Super cool data structure.
I wonder how much utility of such special-purpose languages will keep getting diminished as AI coding becomes a staple in programming and software engineering.
"Modern programming languages reflect a consensus on the the most important programming concepts, including lexically scoped variables, closures, objects, pattern matching, and type parametricity. Why, then, yet another programming language?"
I don't want to be too nitpicky but ... the sentence has two "the", aka "the the most important". It is a really irrelevant error, but on the other hand, has nobody ever read the documentation through slowly, before publishing? Because then this means lack of care and interest. Again, people make typos, that's ok, but if you try to promote a new language, you should at the least have read your own (!!!) writing once. And I am quite certain that the author has not bothered to check his own primary writing here, not even once. So why would he then expect others to want to use a new programming language? Sure, that typo means nothing at all about the programming language itself, but as I got older I also realised that many great language designers are horrible at writing documentation. I'd much rather use languages that are very well documented. Naturally this is a tiny issue here, but if you don't even care about typos in the primary introduction, it makes one wonder about the long term focus of the language as such.
Once you have a bicameral syntax*, is there much point left in formal language theory? For instance, why would you still need complicated notions like LR(k) grammars (which Wikipedia confuses with LR(k) parsers)? I ask out of genuine confusion: I've been reading about formal grammars, and have even added to Wikipedia - but I'm still puzzled as to why PL designers might choose to have hard-to-parse syntaxes. Why don't people instead adopt an intermediate syntax like Rhombus's shrubbery notation†?
"Modern programming languages reflect a consensus on the most important programming concepts, including lexically scoped variables, closures, objects, pattern matching, and type parametricity. Why, then, yet another programming language?"
I love this as a start. More programming languages need to start the conversation this way.
However, it whiffs after this when it fails to answer the question. Or at least fails to answer it in a way I understand. The next paragraph should not start with "Beyond the basics, there are still more good ideas for programming constructs than can fit in any one language specification." - cut straight to what the "programming constructs" are.
This section ends with "approachable" and "extensible". These are nothing. When considering the reasons for a language, look at the negation. Nobody writes a language to be "unapproachable"... well, unless you're on the esolang wiki, but that's not really what we're talking about here. Nobody really wants to stick "non-extensible" on their language either... where we all disagree is in the how one extends things. As someone reading this screen to decide if I'm interested these attributes mean nothing to me.
The page does get around to making it clear that there is a huge focus on macros, which is something, but it takes a while to get there.
That's a legitimate selling point. It's especially a selling point if you can explain clearly how this is different from just using Scheme directly. I have no idea if your language does this but I've long thought that it would be interesting to have a macro-focused language that went all-in on making them debuggable. Have the language compiler and runtime support dynamically exploring them, expanding them in your editor, re-contracting them, full debugging support, just go all-in on supporting that work flow. That would be an example of that sort of thing.
I'm coming from Go, so apologies in advance if these questions seem a little weird:
How do I distribute my Rhombus programs? Can I cross compile to other architectures/OSs, ideally with a static binary?
What about libraries? Is there a good package manager? I presume from the post that the library ecosystem is pretty immature (maybe the Racket ecosystem is larger). Can I easily build a CRUD web app?
Is concurrency easy to make correct? Are tests easy to write? Tests involving concurrency? Race detection?
Dev experience: is it statically typed? I couldn't really tell from a quick search. Will the build system make a fast feedback loop for me and LLMs? Is it IDE friendly (auto complete, find all references, etc)? Is there language server support so I can bring my own editor? Will the macros mean I have to learn a bunch of DSLs to use anyone's library? Do the DSLs have IDE support?
Wow that's a lot of questions ;) It looks like a fun language in any case. And the fact that its even possible to make a Pythonic language on top of a LISP is its own showcase for Racket's power
> How do I distribute my Rhombus programs? Can I cross compile to other architectures/OSs, ideally with a static binary?
You can compile them inside DrRacket and distribute the .exe or equivalent. I used that a few times to send programs written in Racket to coworkers that are not programmers (remember to add an icon so it looks professional).
> What about libraries? Is there a good package manager? I presume from the post that the library ecosystem is pretty immature (maybe the Racket ecosystem is larger).
Some libraries have been ported to make them more idiomatic, in particular changing the name of the functions and fixing the different meaning of "list". Anyway, you can import any library of Racket from Rhombus and vice versa https://docs.racket-lang.org/rhombus-guide/Modules.html
> Can I easily build a CRUD web app?
Sorry, I never tried.
> Dev experience: is it statically typed? I couldn't really tell from a quick search.
It's optional. You can add statically types when you want and the code will be more efficient and get compile time errors. Or avoid them and get run time error.
> Will the build system make a fast feedback loop for me and LLMs?
Sorry, I never tried.
> Is it IDE friendly (auto complete, find all references, etc)? Is there language server support so I can bring my own editor?
auto complete: no (I think)
find all references: yes
> Will the macros mean I have to learn a bunch of DSLs to use anyone's library? Do the DSLs have IDE support?
Most macros try to blend with the language and be invisible, but it's possible to write weird and bad macros too. Most libraries should not define weird macros.
Anyway, some internal parts of Racket like `for` or `match` are implemented in Racket and are like two complete DSLs on their own.
24 comments
[ 3.5 ms ] story [ 38.8 ms ] thread* approachable and easy to use for everyday purposes, with a readable indentation syntax; and
* uniquely customisable with an _open-compiler API_ that is accessible to a wide audience.
Is this an issue in Rhombus? Or Racket?
Rhombus is a novel notation (that is implemented as a Racket macro) which eliminates the need for almost all parentheses. They have a handful of code snippets on their homepage.
[1] Racket doesn't distinguish between parentheses and brackets, so programs could be paren-free. In practice, brackets are only used in a few key places: https://docs.racket-lang.org/reference/if.html#%28form._%28%...
The Rhombus implementation is about 70% Racket!
Summer Rhombus picture competition 2026 - https://news.ycombinator.com/item?id=48546270 - June 2026 (2 comments)
Rhombus Language - https://news.ycombinator.com/item?id=43394881 - March 2025 (158 comments)
Rhombus: Macro-extensible language with conventional syntax built on Racket - https://news.ycombinator.com/item?id=41151439 - Aug 2024 (97 comments)
State of Rhombus (programming language) - https://news.ycombinator.com/item?id=30314109 - Feb 2022 (17 comments)
Anyway, my main initial concern was how to make good macros without s-expressions. There is a nice video by Matthew Flatt in RacketCon 2023. The first 6 minutes and 20 seconds are internal stuff, so skip to the 380s that I added in this link: https://www.youtube.com/watch?v=OLgEL4esYU0&t=380s He takes like another 6 minutes to explain the general idea and make some wishes, and then at the 12m mark he defines macros in Rhombus and makes the wish real in just 2m (with some enhancements later).
Then there is nothing special about having the brackets around. To start with, text can be just as readable:
And one can use stack base syntax, or define a static default arity to infix notation, example two, so `times plus 1 2 3` is not ambiguous and is really clearly like (1+2)*3 with such a convention. Then you can shift arity with reserved word so `unary plus 1` is like `+1` or `arity 5 action one two three four`, or going back to explicit marker like `(` and `)` or `do` and `go` to group stuffs without explicitly quantified numbering.I think my favorite thing is the `…` operator. Go check it out. It’s not like the splat operator in other languages, though it does give that feel initially. It’s much more general: it works with nested data structures and can take the place of a `map` operation.
The best part of `…` is that it is not a built-in thing—it’s just a macro! The magic is that Rhombus lets you define different macros depending on whether or not the macro identifier appears in binding context (left side of `=`), expression context, or some other contexts. IIRC you can even define your own contexts too.
Rhombus takes the best-in-class macro system of Racket and somehow finds a way to improve upon it. I say this after researching and comparing detailed metaprogramming features across a dozen different languages. Rhombus is a very neat little language.
Last thing: Rhombus’ main data type, the list, is implemented with an RRB tree. RRB trees support structural sharing, functional updates, and have O(log n) iterate, insert, delete, append, and arbitrary read operations. The constant factor on that is tiny: I think it’s like log_16 or log_32. They’re designed to be very cache friendly. Super cool data structure.
https://carolina.codes
https://docs.racket-lang.org/shrubbery/index.html
I don't want to be too nitpicky but ... the sentence has two "the", aka "the the most important". It is a really irrelevant error, but on the other hand, has nobody ever read the documentation through slowly, before publishing? Because then this means lack of care and interest. Again, people make typos, that's ok, but if you try to promote a new language, you should at the least have read your own (!!!) writing once. And I am quite certain that the author has not bothered to check his own primary writing here, not even once. So why would he then expect others to want to use a new programming language? Sure, that typo means nothing at all about the programming language itself, but as I got older I also realised that many great language designers are horrible at writing documentation. I'd much rather use languages that are very well documented. Naturally this is a tiny issue here, but if you don't even care about typos in the primary introduction, it makes one wonder about the long term focus of the language as such.
* - https://parentheticallyspeaking.org/articles/bicameral-not-h...
† - https://docs.racket-lang.org/shrubbery/index.html?fam=Rhombu...
"Modern programming languages reflect a consensus on the most important programming concepts, including lexically scoped variables, closures, objects, pattern matching, and type parametricity. Why, then, yet another programming language?"
I love this as a start. More programming languages need to start the conversation this way.
However, it whiffs after this when it fails to answer the question. Or at least fails to answer it in a way I understand. The next paragraph should not start with "Beyond the basics, there are still more good ideas for programming constructs than can fit in any one language specification." - cut straight to what the "programming constructs" are.
This section ends with "approachable" and "extensible". These are nothing. When considering the reasons for a language, look at the negation. Nobody writes a language to be "unapproachable"... well, unless you're on the esolang wiki, but that's not really what we're talking about here. Nobody really wants to stick "non-extensible" on their language either... where we all disagree is in the how one extends things. As someone reading this screen to decide if I'm interested these attributes mean nothing to me.
The page does get around to making it clear that there is a huge focus on macros, which is something, but it takes a while to get there.
That's a legitimate selling point. It's especially a selling point if you can explain clearly how this is different from just using Scheme directly. I have no idea if your language does this but I've long thought that it would be interesting to have a macro-focused language that went all-in on making them debuggable. Have the language compiler and runtime support dynamically exploring them, expanding them in your editor, re-contracting them, full debugging support, just go all-in on supporting that work flow. That would be an example of that sort of thing.
How do I distribute my Rhombus programs? Can I cross compile to other architectures/OSs, ideally with a static binary?
What about libraries? Is there a good package manager? I presume from the post that the library ecosystem is pretty immature (maybe the Racket ecosystem is larger). Can I easily build a CRUD web app?
Is concurrency easy to make correct? Are tests easy to write? Tests involving concurrency? Race detection?
Dev experience: is it statically typed? I couldn't really tell from a quick search. Will the build system make a fast feedback loop for me and LLMs? Is it IDE friendly (auto complete, find all references, etc)? Is there language server support so I can bring my own editor? Will the macros mean I have to learn a bunch of DSLs to use anyone's library? Do the DSLs have IDE support?
Wow that's a lot of questions ;) It looks like a fun language in any case. And the fact that its even possible to make a Pythonic language on top of a LISP is its own showcase for Racket's power
You can compile them inside DrRacket and distribute the .exe or equivalent. I used that a few times to send programs written in Racket to coworkers that are not programmers (remember to add an icon so it looks professional).
You can use the command line too, and it support cross compiling, but I never used it https://docs.racket-lang.org/raco-cross/index.html
> What about libraries? Is there a good package manager? I presume from the post that the library ecosystem is pretty immature (maybe the Racket ecosystem is larger).
Some libraries have been ported to make them more idiomatic, in particular changing the name of the functions and fixing the different meaning of "list". Anyway, you can import any library of Racket from Rhombus and vice versa https://docs.racket-lang.org/rhombus-guide/Modules.html
> Can I easily build a CRUD web app?
Sorry, I never tried.
> Dev experience: is it statically typed? I couldn't really tell from a quick search.
It's optional. You can add statically types when you want and the code will be more efficient and get compile time errors. Or avoid them and get run time error.
> Will the build system make a fast feedback loop for me and LLMs?
Sorry, I never tried.
> Is it IDE friendly (auto complete, find all references, etc)? Is there language server support so I can bring my own editor?
auto complete: no (I think)
find all references: yes
> Will the macros mean I have to learn a bunch of DSLs to use anyone's library? Do the DSLs have IDE support?
Most macros try to blend with the language and be invisible, but it's possible to write weird and bad macros too. Most libraries should not define weird macros.
Anyway, some internal parts of Racket like `for` or `match` are implemented in Racket and are like two complete DSLs on their own.