Rendered at 13:39:45 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
ashton314 12 hours ago [-]
I’ve written a little library Rhombus.
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.
bjoli 8 hours ago [-]
Finally someone uses the rrb tree as their main data structure! I implemented it for c# and the performance tradeoff compared to List<> was smaller than i had thought.
Just a little nitpick on the repo root: "This is not the readme you want, Please go to the src directory." => But there is no readme in src directory
bjoli 21 minutes ago [-]
Thanks! I havet always been linking to the Collections subdir so I have missed this dumb issue. Will fix next time I use a computer. Might be some time though.
If you have any questions about the trees, feel free to ask.
WalterGR 11 hours ago [-]
> I say this after researching and comparing detailed metaprogramming features across a dozen different languages.
I’m very interested in this. What was your research approach? Are there resources you can recommend beyond the documentation for individual languages?
Lots and lots of documentation, some experimentation, and asking people. :)
TeMPOraL 2 hours ago [-]
> 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.
Something akin to `destructuring-bind' in Common Lisp?
vaylian 3 hours ago [-]
> I think my favorite thing is the `…` operator. Go check it out.
I appreciate your enthusiasm. But three dots are really hard to google. Can you provide a link?
That's both extremely neat and, for the time being, extremely hard for me to get my head around. I got it round monads, so I imagine it's just a matter of time!
gus_massa 12 hours ago [-]
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).
What with the term itself, is that some monthy python reference or related to tree algebraic structure?
ashton314 9 hours ago [-]
Matthew Flatt picked “shrubbery” because it’s tree-like but not fully expanded, so it tends to be more broad/flat than deep like a tree. Hence also the term “enforrestation” when you fully expanded it.
I think the Monty Python reference is just a happy coincidence.
shevy-java 6 hours ago [-]
The knights who say Ni demand a shrubbery.
psychoslave 9 hours ago [-]
Nice to get so much insightful feedbacks. That's the kind of exchange that make HN still sometime interesting.
brightball 11 hours ago [-]
I'd love to get a talk on this at the 2027 Carolina Code Conference (polyglot and cybersecurity). Call for Speakers will open in January.
Looks like a real conference - but the first thing you see is a large image of Rick Astley ?!
spdegabrielle 2 days ago [-]
Rhombus is designed to be
* 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.
cptmurphy 1 days ago [-]
Racket is already approachable and easy to use for everyday purposes
bjoli 1 days ago [-]
A lot of people hate sexprs. Even seemingly reasonable folks.
I imagined they have met students that really struggle with the syntax, while grokking the concepts easily.
I myself have heard "the parentheses are hard to balance" and "after a while you dont even see the parentheses" enough times that I think maybe both can be correct.
iLemming 10 hours ago [-]
> A lot of people hate sexprs
In all my time I have never come across a single Lisper, neither in person nor online, and I know far more than a few dozens, who once grokked the REPL-driven workflow and the structural editing idioms only to later, for whatever reason, suddenly start disliking or even hating s-expressions.
All that so-called "hatred" stems from unfamiliarity. People fuss about Lisps lacking static types, without a single clue about how a "true" REPL trades them off for something different. They compare it to a Python or C# REPL and think "it ain't a big deal". Well, the Lisp REPL is quite different, and yes, a major deal - every single part of the Read-Eval-Print-Loop differs. They complain about "hard to deal with parentheses" and "I can't refactor without types" while having no clue how amazingly nice structural editing is in practice, that you never even think about parens - you only see structure, order and reason.
adastra22 7 hours ago [-]
This is survivorship bias. People who don't like s-expr aren't lispers.
I've used Lisp before. I can read s-expr code. Unfamiliarity is not the issue. I just don't like them. I don't like Haskell/ML either, and I've written large projects in both, so it's not a Lisp-specific thing.
alekq 5 hours ago [-]
Considering your experience and preferences, what do you like?
weatherlight 2 hours ago [-]
I love Lisps, ML-family languages, etc. Languages like Java or Go are just painful for me to program in, and I know I’m probably in the minority there.
But honestly, I think a lot of it comes down to the fact that syntax carries semantic expectations. Certain syntax makes you expect a certain model of programming: mutability, imperative control flow, objects everywhere, etc.
Gleam is a good counterexample. It has an ALGOL-ish syntax, but semantically it’s a functional language, and it’s wonderful to read/write.
Same with Ruby: the parts of Ruby that still make me smile are mostly the parts that feel Lisp-adjacent.
It’s kind of wild that we live in a world where, for most programmers, syntax seems to matter more than semantics.
rtpg 2 hours ago [-]
I think if you believe that the aids types give for refactoring are equivalent to structural editing, then you are the one who might not get the value of typing information (I say this as a Python person, and am totally willing to accept lack of typing info in plenty of situations)
REPLs are nice and good, but when you're working on large enough systems it's nice to have some static foundations for your facts.
lmm 8 hours ago [-]
> In all my time I have never come across a single Lisper, neither in person nor online, and I know far more than a few dozens, who once grokked the REPL-driven workflow and the structural editing idioms only to later, for whatever reason, suddenly start disliking or even hating s-expressions.
And we've never seen bullet holes in these parts of the plane, so there's no point putting armour there.
bjoli 8 hours ago [-]
As I said, i think they have been teaching long enough to have a pretty good basis for the claim that racket's syntax can be a problem.
I am firmly in the "after a while you don't see the parentheses" camp, but I have a friend who I respect a lot who works in clojure (with Emacs/cider/paredit) that just doesn't like it.
I mean, I prefer sexprs above all other syntaxes, and I have had people tell me I just need to get used to indentation syntax or whatever they fancy.
jitl 9 hours ago [-]
well, i guess i know what the grandparent was talking about when they said 'I myself have heard [...] "after a while you dont even see the parentheses" enough times [...]'. Thanks for the example.
IshKebab 1 hours ago [-]
It's not unreasonable to dislike coding in s-expression syntax. It is not very readable.
There's a reason the vast majority of programming languages (especially weighted by popularity) use more traditional syntax.
drob518 11 hours ago [-]
My editor balances my parentheses (Emacs Paredit). I rarely think about them. I just think structurally and the editor manages the details.
psychoslave 9 hours ago [-]
It really feels like, "when I move through the wasteland, I only focus on the path and GPS is guiding me well".
For some reasons, people tend to prefer having a walk in a forest rather than in z wasteland.
drob518 5 hours ago [-]
Look, if you’re committed to Blub, don’t let me talk you out of it.
spdegabrielle 29 minutes ago [-]
I agree 100%. Racket is Awesome.
The Rhombus implementation is about 70% Racket!
jitl 10 hours ago [-]
For you, perhaps. I've never been able to get into lisp style sexpr syntax languages :'(
ashton314 9 hours ago [-]
)
There matched your paren for you.
psychoslave 2 hours ago [-]
Don’t you know that :’( is actually a trigraph for meta-quote-expression·opening ? Such a a reckless move as a lone mere literal closing bracket could destabilize the cosmic equilibrium entirely!
RetroTechie 3 hours ago [-]
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).
Is this an issue in Rhombus? Or Racket?
ginko 14 hours ago [-]
Adding significant whitespace to a new language feels like a bad choice. It's not terrible but I do think it was a bad call for Python in hindsight.
adrian_b 4 hours ago [-]
At least here they provide an alternative syntax that does not need significant indentation, so a program structure may be written on a single line.
cmoski 9 hours ago [-]
Massive fail. I dread having to move code around my F# codebase.
pasquinelli 13 hours ago [-]
why do you think it was a bad choice?
ginko 13 hours ago [-]
It‘s a source of problems with mismatched tabs/spaces being used for indentation between team members for fairly little upside.
Imo it also makes moving blocks of code more cumbersome.
miffi 9 hours ago [-]
Shrubbery, Rhombus's first-pass indentation-sensitive syntax, has a syntax form to facilitate copy-paste.
With guillemets, « and », you can make a section of Shrubbery code indentation-insensitive. The idea for copy-paste it to "armor" the section you want to copy with guillemets in the right places, and unarmoring it after posting.
This needs editor support to do fluidly, but imo it's much better than trying to copy-paste the indentation-sensitive syntax.
I can't tell from my 5 minutes of poking DrRacket whether it supports this "armoring", I've been writing Shrubbery in nvim, which, unsurprisingly, does not support it.
adastra22 7 hours ago [-]
That's horrifying.
rscho 4 hours ago [-]
At least it shows that the authors are aware of this issue and planned for it.
rmunn 5 hours ago [-]
Any language with significant indentation ends up specifying "Indent with spaces, not tab characters" for just that reason. As I recall, Python had that as a recommendation while F# ended up with it as a requirement, but it's been a while since I looked at that so I could be wrong. But in my experience, the category "people who complain about significant whitespace" is nearly a subset of the category "people who prefer tabs over spaces for indentation".
(Moving blocks of code around is not a real problem if your editor is capable of easily highlighting the thing that was just pasted. Because then you just hit that key binding, then press `>` or `<` — or Tab/Shift+Tab if you are using an inferior editor ;-) — until the indentation is where you need it. I haven't found it to be a big problem in practice when writing Python, though mileage will likely vary).
adrian_b 4 hours ago [-]
For me, the alternative solution makes much more sense for a language with significant indentation, i.e. to use only tabs for indentation and to completely prohibit spaces before the first printable character of a line.
I do not know why I have never seen this solution in practice.
rmunn 3 hours ago [-]
It depends on the language's indentation requirements. That can work in Python, where you never need to line things up with characters above that aren't a multiple of an indent level. But in F#, at least a few years ago when I tried it, there are times when you would need (or strongly want) to line things up with other characters. For example, this example from https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/...:
functionName
arg1
arg2
arg3
(function
| Choice1of2 x -> 1
| Choice2of2 y -> 2)
Note how the | needs one extra space in order to line up with the word "function", due to the open parenthesis. If you're using tabs for indentation, that means you need a series of tabs plus one trailing space after the tabs, in order to line up the | correctly.
Any situation where you must have a mixture of tabs and spaces for code to work right leads to a nightmare. Because it makes you have to turn on visible whitespace in your editor and peer closely at the lines. I have a simple rule: "Do NOT make me care whether there are tabs or spaces in this file!" If it's significant whether a line is indented with a tab or space, then that rule is broken, and you're probably in for a bad time. (Case in point: Makefile syntax).
adrian_b 1 hours ago [-]
I did not take this in consideration, because for such code, with brackets and separators, I prefer to align the separators with the opening and closing brackets, like this:
( ...
| ...
| ...
| ...
)
or
{ ...
; ...
; ...
; ...
}
ginko 1 hours ago [-]
>Because then you just hit that key binding, then press `>` or `<` — or Tab/Shift+Tab if you are using an inferior editor ;-) — until the indentation is where you need it.
But that's cumbersome compared to moving the block of code and hitting Tab to have your superior editor immediately indent the block at the right level.
IshKebab 1 hours ago [-]
That's why you use an autoformatter.
IMO the biggest downside is that it gets awkward to do closures and inline expressions and things like that. For example Python's `lambda` and if-else expression which are super weird and special snowflakey compared to the equivalents in e.g. Rust or OCaml or even Tcl.
Maybe there's a way to do it nicely; I haven't thought about it too much.
ginko 11 minutes ago [-]
You can't autoformat broken indentation with significant whitespace since it would make the program not parse (or parse incorrectly)
Yes, Chez Scheme is fast but it took a lot of time (a few years!) to make the compiler translate Rhombus/Racket code to fast Chez Scheme code. And there are still a few rough corners to fix...
Also, Matthew implemented flonum unboxing to make code that uses a lot of floating points like x10 faster. I added type recovery, that gives a 10% boost in many cases. And I'm probably missing a few similar features.
In most cases the Chez Scheme team also was involved. Those changes were upstreamed, so you can enjoy them in Rhombus, Racket and Chez Scheme.
poulpy123 7 hours ago [-]
No instances of blazingly detected in the paragraph "is it fast ? ", I guess the answer is not very
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 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.
gus_massa 2 hours ago [-]
Thanks for the report. I just made a PR to fix it.
I was not involved in writing this, but in my experience it's better to edit the text in Google Docs or something similar that catches all these easy typos. But it's harder to collaborate and make it git friendly, so I guess they just used a standard editor that has less support for this kind of errors.
bbkane 53 minutes ago [-]
Haven't tried it, but isn't collaborative editing what the zec.dev people are working on?
avarun 6 hours ago [-]
Extremely poor reasoning to assume that an author, upon reading his own primary writing once, is guaranteed to catch a typo of this nature.
monkamonme 9 hours ago [-]
[flagged]
dartharva 11 hours ago [-]
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.
psychoslave 9 hours ago [-]
With current LLM I am not sure. Using macro, you can often spare a lot of explicit code boilerplate. So token efficiency. On the other hand, will LLM shine in such a paradigme, where picking the right abstraction is more useful than generating large amount of lines?
Maybe it's a lake of training set, but just roaming the fine article, it already mention a LLM generated project which is more looking like Java idiomatic rather than something authors would consider elegant Rhombus code.
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://github.com/bjoli/RrbList/tree/main/src/Collections
Just a little nitpick on the repo root: "This is not the readme you want, Please go to the src directory." => But there is no readme in src directory
If you have any questions about the trees, feel free to ask.
I’m very interested in this. What was your research approach? Are there resources you can recommend beyond the documentation for individual languages?
Lots and lots of documentation, some experimentation, and asking people. :)
Something akin to `destructuring-bind' in Common Lisp?
I appreciate your enthusiasm. But three dots are really hard to google. Can you provide a link?
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).
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)
https://docs.racket-lang.org/shrubbery/index.html
I think the Monty Python reference is just a happy coincidence.
https://carolina.codes
* 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.
I imagined they have met students that really struggle with the syntax, while grokking the concepts easily.
I myself have heard "the parentheses are hard to balance" and "after a while you dont even see the parentheses" enough times that I think maybe both can be correct.
In all my time I have never come across a single Lisper, neither in person nor online, and I know far more than a few dozens, who once grokked the REPL-driven workflow and the structural editing idioms only to later, for whatever reason, suddenly start disliking or even hating s-expressions.
All that so-called "hatred" stems from unfamiliarity. People fuss about Lisps lacking static types, without a single clue about how a "true" REPL trades them off for something different. They compare it to a Python or C# REPL and think "it ain't a big deal". Well, the Lisp REPL is quite different, and yes, a major deal - every single part of the Read-Eval-Print-Loop differs. They complain about "hard to deal with parentheses" and "I can't refactor without types" while having no clue how amazingly nice structural editing is in practice, that you never even think about parens - you only see structure, order and reason.
I've used Lisp before. I can read s-expr code. Unfamiliarity is not the issue. I just don't like them. I don't like Haskell/ML either, and I've written large projects in both, so it's not a Lisp-specific thing.
But honestly, I think a lot of it comes down to the fact that syntax carries semantic expectations. Certain syntax makes you expect a certain model of programming: mutability, imperative control flow, objects everywhere, etc.
Gleam is a good counterexample. It has an ALGOL-ish syntax, but semantically it’s a functional language, and it’s wonderful to read/write.
Same with Ruby: the parts of Ruby that still make me smile are mostly the parts that feel Lisp-adjacent.
It’s kind of wild that we live in a world where, for most programmers, syntax seems to matter more than semantics.
REPLs are nice and good, but when you're working on large enough systems it's nice to have some static foundations for your facts.
And we've never seen bullet holes in these parts of the plane, so there's no point putting armour there.
I am firmly in the "after a while you don't see the parentheses" camp, but I have a friend who I respect a lot who works in clojure (with Emacs/cider/paredit) that just doesn't like it.
I mean, I prefer sexprs above all other syntaxes, and I have had people tell me I just need to get used to indentation syntax or whatever they fancy.
There's a reason the vast majority of programming languages (especially weighted by popularity) use more traditional syntax.
For some reasons, people tend to prefer having a walk in a forest rather than in z wasteland.
The Rhombus implementation is about 70% Racket!
There matched your paren for you.
Is this an issue in Rhombus? Or Racket?
With guillemets, « and », you can make a section of Shrubbery code indentation-insensitive. The idea for copy-paste it to "armor" the section you want to copy with guillemets in the right places, and unarmoring it after posting.
This needs editor support to do fluidly, but imo it's much better than trying to copy-paste the indentation-sensitive syntax.
The Guillemets syntax is described here: <https://docs.racket-lang.org/shrubbery/group-and-block.html#...>
I can't tell from my 5 minutes of poking DrRacket whether it supports this "armoring", I've been writing Shrubbery in nvim, which, unsurprisingly, does not support it.
(Moving blocks of code around is not a real problem if your editor is capable of easily highlighting the thing that was just pasted. Because then you just hit that key binding, then press `>` or `<` — or Tab/Shift+Tab if you are using an inferior editor ;-) — until the indentation is where you need it. I haven't found it to be a big problem in practice when writing Python, though mileage will likely vary).
I do not know why I have never seen this solution in practice.
Any situation where you must have a mixture of tabs and spaces for code to work right leads to a nightmare. Because it makes you have to turn on visible whitespace in your editor and peer closely at the lines. I have a simple rule: "Do NOT make me care whether there are tabs or spaces in this file!" If it's significant whether a line is indented with a tab or space, then that rule is broken, and you're probably in for a bad time. (Case in point: Makefile syntax).
But that's cumbersome compared to moving the block of code and hitting Tab to have your superior editor immediately indent the block at the right level.
IMO the biggest downside is that it gets awkward to do closures and inline expressions and things like that. For example Python's `lambda` and if-else expression which are super weird and special snowflakey compared to the equivalents in e.g. Rust or OCaml or even Tcl.
Maybe there's a way to do it nicely; I haven't thought about it too much.
Also, Matthew implemented flonum unboxing to make code that uses a lot of floating points like x10 faster. I added type recovery, that gives a 10% boost in many cases. And I'm probably missing a few similar features.
In most cases the Chez Scheme team also was involved. Those changes were upstreamed, so you can enjoy them in Rhombus, Racket and Chez Scheme.
* - https://parentheticallyspeaking.org/articles/bicameral-not-h...
† - https://docs.racket-lang.org/shrubbery/index.html?fam=Rhombu...
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.
I was not involved in writing this, but in my experience it's better to edit the text in Google Docs or something similar that catches all these easy typos. But it's harder to collaborate and make it git friendly, so I guess they just used a standard editor that has less support for this kind of errors.
Maybe it's a lake of training set, but just roaming the fine article, it already mention a LLM generated project which is more looking like Java idiomatic rather than something authors would consider elegant Rhombus code.