Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

[flagged]


As someone who writes a lot of Ruby and has for a long time, I have never thought the metric Ruby optimizes for is “intuitive” (I think it is, but been doing it too long / too close to it so it’s intuitive to me)

The stated optimization from Matz (who created Ruby) is “developer happiness”

The important optimization for me is “fidelity to business logic”, eg less cruft and ruby syntactic sugar means you could sit at your computer and read your business rules (in code) out loud in real time and be understood by a non-dev


Those colons are symbols, and (as a non-rubyist), yes, I think they were a bad idea.

Ruby symbols (and atoms in Lisp / Erlang / Elixir) are a performance hack, they are basically "interned" strings. They're immutable and are mostly used for commonly-repeated values, e.g. names of keyword arguments, enum values etc. Unlike strings, they're supposed to be treated as a single, opaque value, with no other properties beyond the name they represent. Most languages don't give you APIs to uppercase or slice symbols, though you can usually convert to strings and back if you really need to.

The performance advantage of symbols/atoms is that they're represented as pointers or offsets into a global pool, which contains their names. This means repeated instances of the same symbol take up much less memory than they would as ordinary strings, as each instance is just a single pointer, and the actual name it represents is only stored once, in the global pool. Comparing symbols is also much faster than strings, as two symbols representing the same name will always have the same offset, turning an O(n) character-by-character comparison into a simple O(1) comparison of pointers.

It's really strange to me that so many high-level languages, which prize themselves on "developer happiness" and "mental compression" force you to think about strings in this way, out of all things.

I think there's something to be said for having a single character that can be used to represent identifiers as strings. Giving your internal string type an interned representation (with automatic interning of literals and a method to intern arbitrary strings) is also an interesting idea, though I know far too little about interpreter design to have an opinion on how much performance difference it would make. Conflating those two ideas together just seems like a really bad deal to me.


No, symbols are immutable strings, strings are mutable strings. Having both mutable and immutable strings is pretty useful.


It just occurred to me that Ruby's symbols are pretty much the same as Rust's string slices. No?


No. A symbol is basically a constant such as for example HTTP_NOT_FOUND. The difference is that you don’t assign it a number, which means less decisions during development. Another difference is that it will be printed as the string, so no to_string boilerplate.

The other colon path: is used for named parameters/keyword args.

It’s the same syntax as a hash/dict, but as a parameter it does not have a default value in this case.

The old syntax, but still supported for hash/dict was “key => value”

Rust’s string slices are the equivalent of Ruby’s slices of an array: myarr[5..18]


You could chuck RubyLLM and still golf it down pretty far. Nothing RubyLLM is doing is magic. Read the linked article that inspired it (which is in Go); there's even less magic there.

Some of the complaints here are just about Ruby syntax, which: shrug.


> def execute(path:)

> why the "incomplete" colon?

Just ruby's syntax to denote 'keyword arguments', i.e. when calling this method, you must explicitly use the parameter name, like so: execute(path: "/some/path")

> class ListFiles < RubyLLM::Tool

> what's with the "<"?

Just ruby's way of denoting inheritance i.e. class A < B means class A inherits from B

> param :command, desc: "The command to execute"

> again, the colons are confusing...

The colons can be confusing, but you get used to them. The first one in :command is denoting a symbol. You could think of it as just a string. Any method that expects a symbol could be rewritten to uses a string instead, but symbols are a tad more elegant (one less keypress). The second one, desc:, is a keyword argument being passed to the param method. You could rewrite it as param(:command, desc: "The command to execute")

I sometimes wonder what ruby would be like without symbols, and part of me thinks the tradeoff would be worth it (less elegant, since there'd be "strings" everywhere instead of :symbols, but it would be a bit easer to learn/read.


Another couple important aspects of symbols:

1. They refer to the same object in memory, so multiple usages of a symbol by the same name (e.g. `:param`) not not add additional memory overhead.

2. Symbols are also immutable in that they cannot be mutated in any way once they are referenced/created.

These properties can be useful in some contexts, but in practice they're effectively used as immutable constant values.


I disagree. symbols are constants, and strings are text. Very clear distinction, relevant when you have syntax highlighting.

Working with json/xml, or anything that has keys and text-values for that matter is a lot better with symbols


> > it uses RubyLLM

> (which itself is a lot more code added to 400 lines claimed by the author).

Most "X in n (<100) lines of code" projects posted on here mean just that. Import 2 million lines of code from libraries and just count the glue code lines.

It's marketing or something.


I just left a comment similar to this: https://news.ycombinator.com/item?id=44012954.


> As a person who's dabbled a bit in Rust and Ruby

You say you "dabbled" a bit in Ruby and then proceed to demonstrate your lack of understading of basic Ruby syntax.


In Dwarf Fortress, the lowest possible skill rank other than no skill is dabbling. What does dabbling mean to you?


To me, dabbled means learned the fundamentals of the language but hasn't written real software in it. I would expect a dabbler to have been exposed to class inheritance and primitives such ss symbols.


Isn't "dabbled" just "superficially touched it"?


hence the word "dabbled".


> As a person who's dabbled a bit in Rust and Ruby, I'm surprised people find Ruby intuitive and simple

IMO it's because they mostly just don't think about the chaos they're doing. You encounter a function call that ends in a hash. Does the function being called use that as a hash or does it explode the hash to populate some extra trailing parameters? You have no way to know without going and looking. To me that's super dumb. To them it's just another day in unexpected behavior land.


Why the us vs them mentality? How is that productive? Did people who love Ruby do something to you?

Pretty hard to grow and learn new concepts if you immediately label anything you don’t understand yet as “super dumb”


This isn't any new concept to learn. There are real consequences to the other people who need to read and improve the code later to not being able to form rapid linear intuition about the meaning of values being passed around programs without looking somewhere else. It's like reading a garden path sentence where the understanding of the beginning can only exist after working backwards from the end. And there's definitely a distinct dichotomy between developers who detect the discommoding and developers who don't.


> You have no way to know without going and looking.

Honestly, this is a feature. If the difference matters, then you are likely doing something wrong.


re: function that ends in a hash

I assume this is referring to passing hashes in as parameters to methods. Ruby 3 made this more explicit; you must use ** to convert a hash into positional arguments and you must use {} around your key/values if the first argument is a hash.


I'm glad the light was eventually seen after 25 years, but that's a significantly breaking change which means the update often doesn't happen. A lot of Ruby 2 codebases still exist with people still doing Ruby 2 bad behaviors.


It was a breaking change, but it was really small and affected only very few usages. Most places just went on with no changes. It was not at all a painful change.

Also Rubyists as a whole tend to update to the newest Ruby fairly fast. There are of course places that don't upgrade quickly (especially legacy systems that are barely touched), but most places with living code bases seems to be very quick when it comes to updating nowadays.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: