I'm not saying this to attack the language, just pointing my current mental picture to ask: what's the magic everybody loves? I know there is something there because it's an almost unanimous view among ruby devs, so I want to get it.
I'm not saying this to attack the language, just pointing my current mental picture to ask: what's the magic everybody loves? I know there is something there because it's an almost unanimous view among ruby devs, so I want to get it.
You’re probably talking about the ability to reopen (or “monkey patch”) classes (which is why defining the same class again can’t be an error). That’s a powerful tool if you use it carefully, especially for debugging or hacking on someone else’s code.
> blocks feel like a more cumbersome/limited version of lambdas
Yes, that’s basically what they are. You could totally write JS-like code and pass even multiple lambdas to methods. However, the most common use case — passing a single important lambda (e.g. to a “map” or “each” method) — gets special treatment and its own language feature.
> what's the magic everybody loves
For me it’s the “batteries included” factor. Ruby can do a lot out of the box and most of the interfaces are well designed with tons of useful methods with descriptive names. It feels like someone cares about my experience and is trying to anticipate what I might actually need.
Also the object oriented mechanisms are easy to understand and don’t feel weirdly bolted on like in Python.
Ruby makes message passing first class. That just changes how you think about programs. In exchange you give up passing functions so our anonymous functions are our blocks (actually just another object that can receive messages). So you don't `list(something)` you `something.list` and that lets you change what `.list` does depending on who `something` is very easily.
Ruby's defining feature is that the line between language author and program author is razer thin. You can completely change the language yourself by extending core classes. This is why we have `1.day` in Rails even though its not supported in the main language. DHH (author of Rails) could add that without consulting Matz (author of Ruby). So lots of stuff gets prioritized to make developers happy because its easy to add.
In Ruby the messages you receive are passed up the chain of ancestors. Your ancestors are a linked list of classes going back to a root class like `Object`. You can modify this linked list at will with mixins and inheritance with complete control (should I go before or after this other receiver).
Ruby's REPL and debugging experience is amazing. I often keep one tab with an `irb` or `rails console` open to sketch things while developing the code for it elsewhere. I'm also always inside a debugger to figure things out. When I'm in Rust or Python I'm met with a very different environment.