180 comments

[ 4.4 ms ] story [ 202 ms ] thread
Kind of offtopic: I did some Ruby and I find some of the conventions really confusing; for example, the lack of “()” when calling a method. You never know if you’re accessing a property of calling a method until you grep the code. Am I the only one who feels this?
It's always a method in Ruby because you can only access @properties in method implementations.

What you're describing holds in e.g. Scala, where it's by design: they feel it should be an easy-to-change implementation detail whether a name is backed by a direct field access or a method. IMO that's a reasonable stance in a functional(ish) world.

But Scala still differentiates between `def shouldBePure: Foo` and `def probablyHasSideEffects(): Bar`.
@vars are data members, not properties.

“Properties”, in most languages that have them, are an way to make method access look like access to data members (no parens, getters just use the name, setters use name + = with the new value on the right of the = instead of in parameter position.)

In ruby you are always calling a method, you can't access a property from outside a class with normal syntax.
Ruby doesn't have properties except as an alias for a certain pattern of methods, and in languages that do have properties they are almost invariably just a layer over calling getter and setter methods.

You seem to confusing “properties” with “data members” which, it is true, Ruby does not permit external access to except via method calls. But properties are a way of calling methods with a syntax that looks like direct member access, not actual direct member access.

I used to find this odd as well, but that feeling came from a misunderstanding of what a "property" is. When you use `attr_reader :foo` what you're actually doing is calling a method that defines a method on the class for accessing `foo`. `a.foo` is not accessing a property, it's calling a method. `a.foo = 2` is not writing to a property, it's calling a method called `foo=`. The "()" can be left out because it's never ambiguous whether you're calling a method, because you're always calling a method.
That's a really helpful way to think about it, thank you!
I remember loving this when I learned Ruby. There's a certain elegance to it.

However, I'd say for practical purposes, it still leaves me with the problem that in my day to day coding I'm left with the same ambiguity. I don't know if I'm calling a simple-assignment auto-generated method that is setting a property, or a method that does all sorts of stuff under the hood.

While I'm still fond of Ruby, I've come to prefer less ambiguity. I like to be able to see at the calling site whether what I'm doing is calling a method or setting a property, and parentheses are a great way to signal that.

As an aside, one thing I didn't like about Elixir was that it also made parentheses optional. Once I realized why this was necessary, and once the formatter was added and enforced parentheses as a default, it stopped being a problem. Still, every language I've used where they're optional have caused weird little problems that never seemed to be outweighed by the convenience (CoffeeScript comes to mind).

But all that said, it's not too high on my list of things to hate on :).

> As an aside, one thing I didn't like about Elixir was that it also made parentheses optional.

Ocaml does something similar. If you have nested function calls in a line of code, the interior calls look just like lisp. But the outermost one omits the parentheses.

The worst part is when you invoke a method like a property but it has side effects.
> I like to be able to see at the calling site whether what I'm doing is calling a method or setting a property

In Ruby, as is also true in many languages that have a syntactic distinction, setting a property is always ultimately calling a method, so the distinction is illusory. What you may want is a purity guarantee (well, that getters are pure and than setters have no effects except on the state specifically backing the property, but the latter gets complicated to apply to nontrivial properties), but most languages that let you distinguish whether properties or methods are exposed in an API don't provide a that kind of guarantee with properties, either, just more boilerplate code to implement them.

And the whole point of properties over exposed data members is to abstract behavior so that implementation changes don't change APIs.

Even when it's not enforced by the language, it can be something enforced as part of the coding style by the team - that Foo vs GetFoo() indicates presence of side effects, or potentially expensive computation.
Indeed. This lax syntax has led to the proliferation of so-called DSLs which are really just Ruby with a few functions pre-loaded. Personally I’d rather they just admit what they are rather than trying to pretend they’re some special thing. In Python it would just be a package that you import * and there’s no shame in that.
No, I'm still struggling with that too. It's probably the main thing that still grates in Ruby syntax for me (along with `unless` and implicit returns). I'm sure it'll become natural as I use the language more, though!

Scala has similar conventions, I believe.

You can never access a property in Ruby from outside the object, you are always calling a method. Calling "attr :foo" just defines two methods, "foo" and "foo=" which then can be used to access the property.

I think this is a rather elegant solution to properties, that you always need to expose them with getters and setters and that properties and methods do not share the same namespace.

Learn more languages, you might like lisp or maybe lua with optional parentheses or maybe even haskell. Don't let small things discourage you from the bigger picture
Honestly, I never could get into the Ruby language. I always kept making mistakes with the syntax and ended up gravitating towards python and relearning JavaScript
Same. I always felt that Python was actually designed for humans and that Ruby had an incomprehensible syntax.
I never did much with Ruby beyond toy problems, but I was impressed by the lengths the language goes to to make it convenient to express what you want to do.

There's one syntax for half-open ranges and another syntax for closed ranges.

You can index an array any number of different ways: "get me the 5th element". "Get me the element three back from the end". "Get me elements 5 through 8 (inclusive)". "Get me 0 through 6 (exclusive)". "Get me the 3-length subarray starting at index 2".

A hash table returns nil by default when you access a key that isn't stored. But you can change the default value as a property of the table itself. Users now don't need to remember to supply their own default value when they're looking in the hash table. Even more, you can specify a function that gets called when a nonexistent key is accessed, to do whatever is appropriate.

All of those are great things. It's easy to translate your algorithm that says "take a stretch of three elements starting from i" into an access that looks like array[i..i+2]. But the semantics of your algorithm start slipping away as you make adjustments like that. If what you're doing is taking substretches of 3 elements each, there's a gain from being able to express it as array[i, 3], as semantically distinct from taking a substretch between two independent bounds that happen to be i and i+2.

But the flip side of this is that if you're not regularly immersed in the language, it's really easy to lose track of precisely which bit of syntax does what.

Ruby was the first language I truly liked programming in. But the ecosystem never clicked with me.
And that’s why it relatively slow compared to e.g. C — which is designed for machines, not humans.
Replace ruby with crystal, and this comment can be removed.
Crystal is not Ruby, nor is it anywhere near as fast as C.
Really? Benchmarks I've seen put it in the same ballpark
I’ve been trying to get into Ruby for a new job and am finding it hard.

Not being designed for machines is right - a lot of the IDEs seem bad and can’t even figure out where your methods come from. I don’t know how the interpreter manages to run it. Multiply the problem by 10 once you add rails and all the methods it generates.

It makes for a good, rapidly developed monolith but most places I’ve worked in recent times are moving to services and micro services and it doesn’t seem cut out for that.

Generally, I think RubyMine is quite good as a Ruby IDE.

You can also use IRb, Ruby's REPL, and #source_location to find definitions, it works for monkeypatches as well if your team is using those.

(comment deleted)
Have you tried RubyMine from Jetbrains? It's the best dev environment I know for ruby.

https://www.jetbrains.com/ruby/

I love Rails but even RubyMine struggles to understand the context of a Rails app. Everything being dynamically required seems to be the real thing that makes it hard to be context aware.
This ^

Perhaps it’s fairer to say a lot of my struggle so far is with a Ruby on Rails project.

I’ve had less exposure to Ruby without the Rails part, and maybe it’s regrettable that’s the case.

I’ve used frameworks in other languages and mostly always been able to dig back to the original source of things but I’ve not had such a positive experience with Rails and any of the IDEs out there.

As dgellow and kawsper pointed out, Rubymine is a good IDE, or Intellij with the Ruby plugin, which is functionally the same thing. Also, vim support for Ruby is amazing. Tim Pope has dedicated a chunk of his life to ensuring this (thanks, Tim). Also, a lot of the core team members have been using Emacs since the beginning. I haven't spent a lot of time with Emacs, but from what I've seen, the Ruby support is pretty great.
That's my biggest problem with Ruby, where you can create a function and suddenly poof, you can use it anywhere. Like I'm writing tests and want to create a util function, so I put it in a different file and I can use that anywhere without having to be explicit with where it came from and was defined. Glad it's not just me but the IDEs as well.
That’s not a Ruby thing. That’s a Rails thing. In Ruby you still have to require your code like every other language.
I'm in the same boat. I'm coming up to speed on a very large, 5 year old monolith RoR codebase.

I fucking hate the thing.

I've done quite a bit of web dev across a pretty large variety of languages (c/c++/c#/php/js/golang/other).

They all have rough edges, but never in my career have I been more frustrated than when dealing with Ruby on Rails.

The tooling is... the best I can call it is bad. Simple things like jump to definition just don't work, basically anywhere, autocomplete is non-existent. RubyMine is the closest to functional, but it's still MILES away from good.

Non of that alone is a deal breaker - I've written sites in plain old notepad or gedit, but when languages have bad tooling, I expect good documentation. Rails is off in la-la magic land though. Docs are hard to find and inconsistent. I'll frequently find documentation that contradicts itself (ex: Are middleware "Set-Cookie" headers delimited by a comma, or returned as an array? Ans - Trick question, the documentation says both in different places, but it's actually a newline, which isn't documented fucking anywhere.)

Trying to just figure out where a method definition lives is needlessly tiring. I asked a long time dev at the company how he finds the source for methods that are magically pulled in by rails. His answer: "I do a global search for "def [name]" and if that doesn't find it, I give up and ask the development slack channel". Personally, I find that mind-boggling.

And honestly, I guess most of my frustration isn't really Ruby. It's Rails. I don't love that Ruby seems to encourage the "make it a dsl!" type programmer, but by itself there are good times/places for that. Rails though? It just doesn't scale for humans.

Rails feels like it started off with a solid idea - Don't worry about the boilerplate, just write productive code, we'll handle the magic. And that works great... up to a point. But that point was years back. Now the whole ecosystem has grown to the point where I HAVE to understand at least some of the magic, but because they didn't want you to see it, it's really, REALLY hard to get good answers about how/where all the various bits play together. Instead you chase outdated docs, bad stack overflow answers, and shitty forum posts.

I came on board pretty excited to pick up Ruby on Rails. A year in and I'm pretty convinced that I'll recommend basically ANY other framework and toolset.

Have you looked at Hanami? https://hanamirb.org/

I'm in the same boat about RoR. I just find its size to be overkill for most uses. Hanami is considerably smaller and lightweight, but not to the point where it's more of a micro-framework (like Roda). I've been happy with it for a number of microservices and some larger websites.

All so incredibly relatable... thank you for sharing your experience.

I have pretty much 1:1 the same struggle and it was (is?) starting to knock my confidence - wondering if I’m just a bad developer for not “getting” it.

I often put off development tasks because I know it will all move at a snails pace trying to drudge through endless magic, having no idea where any of it comes from, getting very little back from Google, and giving up.

“Ruby is designed for programmers, not end users”

It's not machines who care about performance. It's the person who has to use the program written. It may sound gentle and altruistic, but when you actually think about it, putting “humans” first is actually an incredibly self-serving sentiment.

When you actually think about it, “humans” is plural, and "self-serving" sure seems singular.

Past that superficiality, a programming language is a mechanism.

I am sincerely curious in what larger context one would evaluate this mechanism at all, and furthermore, deem it "an incredibly self-serving sentiment".

There is already an ideal programming language for computers. It's bytecode. All high level languages after built for people, not computers, to make it reasonable for us to collaborate and maintain our own code. The computer itself doesn't care for anything beyond 1s and 0s.
And computers are built for people, to make it reasonable for us to collaborate and maintain our own (non-programming) work.

Dismissing performance concerns because you're designing a language “for humans” is actually glossing over a quite large number of other “humans” (i.e. non-programmers) who do have a stake in the choice, but not so much say in it besides “why is my computer so slow lately”. Well, it's slow because you thought type checking is for know-it-all ivory-tower academics and pedantic asshole compilers, so you chose JavaScript (or whatever “forgiving” language is in vogue these days; the OP is about Ruby, but it doesn't really matter), and so the user has to wait until the JS engine finishes JITting your code over and over again to infer type information that should have been available at compile time in the first place. Rinse and repeat for each app, and now they have to replace their laptop every few years to catch up with ever-growing (for no good reason!) RAM requirements.

Claiming that a programming language is “designed for humans” much too often amounts to saying “my (programmer's) convenience and satisfaction is more important than yours (user's)”. And that is an incredibly arrogant thing to say, as superficially gentle as it may seem at first glance.

I'm not arguing against high-level languages; I'm arguing against disregarding performance in the name of programmer convenience. It's quite possible to design a high-level language in a manner that doesn't stand in the way of making its implementations performant. There are some recent developments on that front.

But if you ignore them, then it's not the “machine's” resources that you're wasting. It's the user's resources.

There's a lot of comments of the form "I tried getting into Ruby and it never clicked" that I want to respond to.

I think that if you're just writing a script to solve a math problem or automate a task, there isn't really a strong argument as to whether you should use Ruby, Python, bash any other high level language. You should probably use whatever you're most comfortable with.

But if you're making an application with a database, RoR is an extremely powerful tool. And this isn't just a case of Ruby having the best library (in the same way that Python has the best scientific computing library). It's a case of the library functionality and the language playing together really well.

Ruby statements look more like natural language statements than those in other languages. This is a really helpful design choice when you're building a crud application. In that context, you're not thinking about X, Y, -Log(X + Y) or whatever.

You're thinking about a new customer, or whether some old customer is a member? of some mailing list, etc

In a weird way, it's similar to how Haskell users love the fact that statements in Haskell are mathematical truths. In the case of logic programming this is a handy feature to have. In the case of writing the business logic of a CRUD app, it's handy if your statements look like natural language statements about the underlying real world objects whose representation you are reasoning about.

I am starting to ignore syntax when I read code now. It doesn't register in my mind most of the time unless I see a sudden paradigm shift or odd dependency behaviour(I think this causes me to snap more than language syntax. Dependencies don't have clear code navigation guidelines, proper structure or docs than the language they are in).

From my perspective, choice of language matters very less compared to the number of experienced programmers you can get at x price. If there are more js developers, then that means you can hire more for less overall. Obviously things are more complicated.

If I want to write software that is going to be used for a long time, then I am going for strongly typed compiled language that will have certain percentage of developers 10 years later than focusing on how beautiful the language is syntactically or how it reasons well. Binaries are easy to distribute and can still be used after source code is no longer available for odd reasons. Anything trendy will get too many breaking changes or fixes. Heck, having visible source code can be liability too in future. I may as well choose something that will be hard to decompile. Not to mention the external dependencies that you will need to mirror or even maintain.

I think most businesses that are dependent on tech can be divided into short lived and very long lived ignoring certain type of software and industries.

For short lived businesses or customers, your stack shouldn't matter much compared to the responsiveness of development. What incentive are there to provide quality software to companies that will live 5 years at best? (Note - quality here refers to ideal stack/code that programmers expect. Eg - unnecessarily performant, kubernetified, micro architecture)

None.

For long term businesses, software is an ongoing cost. They can afford to renew their software every 10 years so why should you write something that is expandable, easy to migrate and another team to take over. Beside, their requirements change drastically over time. It will end up being a monolith.

I don't have to work right now but if I ever do, I am gonna work on the interesting bits while hiring someone in a third world country to outsource parts that I don't from my job.

I want to solve problems and reach goals. Syntax doesn't provide enough value on its own in a general programming language.

I like your post a lot. I don't disagree with anything in it per se, but I think there are a couple qualifications worth making.

> From my perspective, choice of language matters very less compared to the number of experienced programmers you can get at x price.

That's fair. But exactly how much you ought to worry about the hiring landscape depends on your situation. At the beginning of a lot of software projects, there is "you" and "your laptop" and "no money." In these cases you should pick the tool that is going to help you get off the ground fastest. You can worry about the hiring landscape if/when you're lucky enough to get there.

> If I want to write software that is going to be used for a long time, then I am going for strongly typed compiled language that will have certain percentage of developers 10 years later than focusing on how beautiful the language is syntactically or how it reasons well. Binaries are easy to distribute and can still be used after source code is no longer available for odd reasons.

Roughly speaking I agree. However, two comments:

1. This is a very broad critique. You can say exactly the same thing about python, bash, perl, etc. It applies to Ruby, but it's not endemic to Ruby.

2. Not everyone is looking at the same time scale. If you are building software for an enterprise that's been around for a few decades, I can totally see the argument for eg Java. But in many cases, the landscape 10 years from now is the wrong thing to optimize for. For some, building a software product that actually lives long enough to have dependency issues is an amazing problem to have.

> I want to solve problems and reach goals. Syntax doesn't provide enough value on its own in a general programming language.

I could have been more explicit in my original post. What I'm lauding about Ruby is more than pretty syntax. I'm arguing that the the whole language dovetails really well with the application framework, both in terms of routing and in terms of db operations. Particularly the latter. There was a recent thread here that was something like "What should I learn in 2020?" and hands-down the winner was "Learn how to use a DB." I think that Rails is a powerful way to approach this.

Yeah, my original comment is disorganised. Essentially, I meant to distinguish between two business sides (there are others) rather than making point for any language or situation.

The compiled language part was an example to long standing businesses where you are aware of many details like software sweeping cycles, culture, goals, requirement changing tendencies, etc.

> That's fair. But exactly how much you ought to worry about the hiring landscape depends on your situation. At the beginning of a lot of software projects, there is "you" and "your laptop" and "no money." In these cases you should pick the tool that is going to help you get off the ground fastest. You can worry about the hiring landscape if/when you're lucky enough to get there.

Yes, see this puts you into short standing business bucket.

> Syntax doesn't provide enough value on its own in a general programming language.

I actually didn't mean this literally. I think of tools as a means to move around and give shape to a product, team, business or yourself. Syntax can be relevant to that while relying on syntax in seldom is a bad idea.

Examples:

People who like ruby syntax and are attracted to it is a different bunch than those who are attracted to java. While you may prefer to use java, you don't necessarily want programmers attracted to java in your team.

Using statically typed language may provide more friction to think about the structure or slow you down a bit which may be important for shaping the product.

In short, you don't want tools to decide your fate. Sometimes, using less than the 'best' is a better choice.

> I think that Rails is a powerful way to approach this.

I strongly disagree with that thought. AR is the best tool to get around properly learning SQL. That's both its greatest strength and it's most fatal weakness.

IMO it's still worthwile learning AR after learning and understanding SQL, but the other way around will just be a headache.

> From my perspective, choice of language matters very less compared to the number of experienced programmers you can get at x price.

I honestly think there's a sweet spot. I have seen brilliant people expertly build massive systems in Java, but there is no doubt in my mind that if they had attempted those in almost any other popular high level language, they would have been more productive. I know I've been very productive in Clojure, for things that I can afford to write in it (performance-wise), and much more productive than I have been in languages I have a lot more experience with.

Definitely.

Your comment proves my point though. You don't need experienced 'java' programmers but simply experienced programmers.

The more time I spend in the industry, the more I tend to believe you should just hire programmers who have a demonstrated ability to produce a high-quality product. Any product. Programming languages and domain-specific knowledge can be learned quickly, and all the best practices and process controls in the world can't replace talent and experience solving problems.
Those things can sometimes be learned quickly, but it takes time. If your company can't have, or doesn't want, productive developers to be spending a lot of time mentoring, then it can be worth it to hire people trained in your working language, possibly even familiar with your style of program or library ecosystem (if you have one of those).
I don't understand why the Node community doesn't have an analogous to Rails. I love the Ruby language, but given that much of my work is on the front-end, I'd love to avoid context-switching between two languages for my stack. Also, with some requirements like server-side rendering, being able to natively do that in my web server is nice. I haven't used Rails since the early 2010s.
They do have Sails but it's nowhere as good as as RoR. At least prefer something fast like Fastify or Koa if using Node.js.
Doesn't this kinda prove the point that Node.js is only more performant when used with micro-frameworks like Express? That Sails failed to match Rails should tell you something. A fair comparison with Express would be something like Grape or Rhoda. Node.js itself should be compared with Rack which is pretty fast.
The fact that Sails never caught on to match or exceed Rails usage doesn't mean the main problem was primarily performance. Rails, for one, has a huge incumbency advantage (2004). Second, Rails is just easier than throwing together a pile of NPM modules. Imagine if you had 0 knowledge of the NPM ecosystem. It'd be quite a lot of decision making to evaluate a basket of modules that could emulate all of what rails provides.
Thworing together a pile of third party NPM modules is a bad decision anyway. This is precisely why we picked Mojolicious to use as a Perl web framework: minimal dependencies, minimal breakage, reimplements some functionality. It turned out to be a good decision as it's also actively maintained compared to the others.
Sails was not in a good way when I used it...
Because Rails is a huge mega framework that tries to do everything in a very opinionated way. We need guys love to compose bigger things out of small things. :-)
So on one hand, adonisjs, feathers, etc., but a lot of nodejs users consider express+npm to be their "rails".
> RoR is an extremely powerful tool

The issue I always had with Rails is that there would come a point where I would want to achieve something which wasn't really in the "blessed path" of a Rails application, and then I would end up with something that felt like a hack to circumvent Rails' default behavior. That, or I would want to do something which is very simple conceptually, but I would have to add some unnecessary complexity and/or ceremony around it to fit into Rails' interfaces.

Also I'm not a huge fan of the Rails' model of having everything from request handling to routing to DB access in one big framework. The needs of each application can be quite varied, and I'd rather plug whatever components together I want to for a given project than to be limited by some outer structure.

> Ruby statements look more like natural language statements than those in other languages

The more I program, the more appreciative I am of a strict compiler. What I've always found with interpreted languages is, while they seem convenient at first, projects inevitably start to slow down under the accumulated "squishiness" due to lack of strictness. I find it's pretty easy to get used to syntax, but there can be a lot of hidden "gotchas" in interpreted code which tend to outweigh any benefits.

Also as far as the natural-language-like syntax, I find that Swift offers a similar benefit, with the added benefit of strong compile-time checks.

(comment deleted)
> The issue I always had with Rails is that there would come a point where I would want to achieve something which wasn't really in the "blessed path" of a Rails application,

I think this is the first part of the insight needed.

The second part, which by far the most productive full stack web dev I know has got completely nailed, is that mostly the right answer to that is to push back on the business/requirements with a good alternative to what they _think_ they want that _is_ in "the blessed path".

A good Ruby dev who has the ability/skill/respect to do that is maybe the closest thing I've ever seen to the mythical "10x engineer" on a consistently repeatable basis...

And this goes for other things besides RoR too, I've got a Python/Django guy who can build amazing stuff in weeks, but he'll tell me why I am not getting what I asked for but this other thing that does the same job (sometimes better) because "that's the right way to do it with Django".

I guess the problem I have with this is that in other toolsets, I can achieve exactly the result I want without compromising for the tool, so Rails and similar frameworks feel restrictive in this way.
Perhaps you should do a bit more reading on these tools. With life experience you will learn that these tools really help you get your work done, and right now you're likely solving what they have already solved for you. Rails is a highly modular architecture with some sane implementations by default, but I promise you there are many pluggable pieces that exist that do just about everything you could ever dream of.
I don't like the suggestion that if I don't care for rails I must be using it wrong. I have worked with many technologies over the years and I know which ones I like and which ones I don't.

I suspect it is an issue of preference. I am sure it is possible to be productive using Rails, but the interface style and overall structure is a bit heavy handed for my taste. I prefer tools which stay out of my way and I'm not terribly fond of working inside an "ecosystem".

> The issue I always had with Rails is that there would come a point where I would want to achieve something which wasn't really in the "blessed path" of a Rails application, and then I would end up with something that felt like a hack to circumvent Rails' default behavior.

As a Rails developer for over 10 years now, I definitely agree that going off the rails (see what I did there?) is nearly always painful. Especially if Rails doesn't totally click for you. I can see why that would drive a lot of people totally nuts.

I think that if Rails really clicks for you then it's possible find a way to solve those problems within the same sort of way of thinking that Rails is coming from. But not everyone works the same way, and that's ok!

> Also as far as the natural-language-like syntax, I find that Swift offers a similar benefit, with the added benefit of strong compile-time checks.

Life is short, if at all possible write code in whatever language makes you happy. If that's Swift for you, well then cheers!

I think focusing on the syntax level is a bit superficial. While Ruby (especially in the context of RoR) lends itself very well to making DSLs and making abstractions, and thus writing superficially good looking, concise, easy to follow (on a syntax level) application code, it really breaks down when the abstraction does not work perfectly the way you want it.

If you have debugged a Rails app and tried to find where in the 10 level call stack a side effect is introduced, knowing that at each level a 'method_missing' could've changed things, and thus you're really looking at a non-linear call stack since each function call can branch out, you'll know the beautiful looking syntax is not free and in fact very costly.

And don't get me started on poorly documented (if any) CoC (black magic)..

CoC means many things. What do you use it to mean here?
Probably "convention over configuration".
my best bet: Convention over Configuration (had to google tbh)
Yeah, sorry for the abbreviation. I meant 'Convention over Configuration'
I agree with you on the comment about abstractions, but I think I would rather have Rails with esoteric code than something less "conventional" with esoteric code.
yeah, esoteric is bad, whether Rails or others. But that's just my impression with Rails, and I'm much more comfortable using other less magical libraries. I guess Ruby is just too good at making abstractions, and I tend to believe that 'making and using abstractions feel great and productive, unless it's made by others'
I think the syntax is very important. It is the aesthetics of a wood floor versus a vinyl floor. Sure, both may get it done, but clean and beautiful syntax that resonants with your brain makes the job more delightful.
> And don't get me started on poorly documented (if any) CoC (black magic)..

I have never liked the idea of (framework-enforced) CoC.

First of all, RoR isn't as CoC as it claims; many things can be configured, which defeats the purpose entirely, and all that remains is the a CoC philosophy.

If Rails would actually enforce CoC, it'd be too restrictive to build anything new with it, so true framework-enforced CoC is not really viable in the real world.

So what people really mean when they say is "Convention over Configuration" they really just mean that the framework doesn't generate a default configuration, but instead the defaults are all encoded within the framework code and its documentation. This is bad. The only benefit is that an empty project looks less cluttered, but that is really only an aesthetic advantage to draw in new users.

The downside is that the project loses documentation. Ideally, I want to jump into a new project, open a config file and be able to have a look at all of its configurations. In Rails I can't do this; I have to either memorize or look up the defaults and then check if they're changed in the current project.

Ultimately, its idea of CoC makes rails easier for starters to get into, but a total pain for people who don't care to get into it and just want to make some specific change and for anyone with a specific goal in mind that doesn't align neatly with how the framework thinks you should do things.

I just didn't like the tooling,it's quite messy. Python is similar enough, I would hate to do things in both.
(comment deleted)
Ruby is truly nice, I just wish I had the option for static typing built into the language, as a human I prefer it because then IDE support is much better for any refactor, etc and getting to maintain other people code.
You're not alone. Stripe has been working on adding types to Ruby with their static type checker, Sorbet: https://sorbet.org/. This seems to have a bit of momentum at this point. Assuming it continues in popularity I'm excited to see how this helps to improve Ruby work in an IDE.
Looks interesting! will have a look.
Strange takeaway in the title.

Mine are:

- He regrets introducing threads. He now prefers other parallelism/concurrency paradigms and is possibly looking into introducing them in Ruby 3 (that part wasn't clear in the interview).

- He regrets adding global variables.

- He regrets not focusing on immutability primitives earlier.

- He and the maintainers team look at Python, JavaScript and Elixir for inspiration.

- He seems a bit disappointed that Ruby is mostly used for web development only and would be happy if it was used in research and AI.

- He regrets not investing even a little effort in static typing earlier but is now working on an optional typing system where you choose to describe types in a separate file. (Reminds me of C/C++ and OCaml header files.)

I hope I’m not subconsciously emulating a sensationalistic journalist here but it doesn’t seem he’s very pleased with the current state of affairs. A lot of changes, indeed inspired from other languages, seem to be on their way to Ruby 3.

---

I’m pretty indifferent to Ruby these days. I’ve worked 6 years with Rails to a moderate financial success back then but the problems were obvious almost from the start: too much magic and implied behaviour, too much global stuff changing below your feet, way too slow DB layer (it’s known that your DB will respond in 2ms and ActiveRecord will proceed to waste 100+ ms on serialisation before and after), managing bigger projects becomes huge pain, and a number of others.

People just keep buying the promise of “but you get to make an MVP really quickly!”. Yeah well, but I want to maintain it past that stage too.

Where I was doing with this is: Ruby is a very okay language and is very nice for sketching. It's readable, has libraries for a ton of stuff, and performs alright (especially without Rails). But I never found good use of it outside of small projects. Any serious business work becomes very painful to maintain and stay on top of for bigger projects. I’m aware there are practices that make it possible (Basecamp is a huge inspiration!) but I personally found them only half-working.

YMMV, of course.

Good points.

Personally, it's a bit puzzling to me why the ML community ran with Python and why there isn't a popular alternative for Ruby. It's very capable in terms of making DSLs.

My hunch is that the number-crunching libraries were better in Python (numpy etc).

I spoke with several data scientists and students in the last 2 years and the consensus was basically two central points:

1. NumPy is really fast and has a lot of features. Even if they don't need all of them they feel more at ease knowing that they can use them should the need arise.

2. Python is very familiar to them, their professors know it, they know it, it's easy to teach to new people in the team so everybody just goes with the flow.

As much as I think the bigger IT area is in a desperate need of innovation... I can actually agree with those two points. Tinkering should be left to us the programmers and sysadmins. Everybody else has a job to do and they cannot and won't spend a lot of time evaluating all tech possibilities.

That's okay. It's our job to tempt them with something irresistible. :)

But those are reasons that are valid afterwards. Why weren't the good numerical libraries developed for Ruby?

Maybe the watershed moment was when MIT switched from Scheme to Python? I don't know.

Really good question. And I have no clue.

But I believe (can't prove) that you are correct on the outset: some big org switched, then a lot of people went like "oh well, Org X can't be wrong", and the rest is history.

This isn't how I remember it. I remember that prior to the scientific python stack, you had to pay for Matlab or mathmatica licenses. The scientific python stack meant that for essentially free, you no longer had to justify licenses at any financial or educational institutions. You could just load up your code and run it against your data. In academia this meant that every student could do their homework on their desktop or laptop (if they were motivated). Even in financial companies, the decision was often made to limit the number of licenses - and in most cases they weren't used to actually run production jobs. Quants had to translate their work to another language with the help of their developers.

With the scientific python stack you entered a new world with unlimited seats, you could at least try to run the same experimental/exploratory code with minimal changes in a production environment, etc.

So in short it didn't need some tentpole user/customer/exemplar. In almost any situation it was free and it started making money as soon as it was downloaded installed and run.

Well, I believe that the native memory model of Python is relatively welcoming to just doing your own thing, but also Python just got there first: NumPy was first released the same year as Ruby on Rails. So Western developers were discovering Ruby while Python was merging two existing scientific programming projects.
My recollection is that Perl had numerical libraries that were crash-prone, and in at least the finance company where I worked that was the backbone for some models for a while. In the early-mid 2000s numpy/scipy got a lot of commercial support, and as I recall the ffi support for this was broader and more unified than anything else - the unifying idea of the numpy array and the ability to load it with data and pass it to everything in the ecosystem just made it work.

At the same time, I saw no substantial interest in persuing the same dedicated effort at the same scale in any other ecosystem. Rails was what everyone did in Ruby (aside: recalling that the ffi changed between 1.x and 2.x and it wasn't a trivial API change, and how the only documentation seemed to be the code, would have broken any prior work... I can't imagine putting long-term effort in this direction), java and jvm hosted languages didn't seem to gain any traction from users for these problem spaces (maybe the inability to easily dynamically allocate more heap on demand in user code made this unfeasible?)

Looking back I think the fact that numerical work has found success being built on a huge foundation of stable libraries that are glued into a dynamic interpreted language and which is then often treated as a finished artifact, I can't think of another major language that is more appropriate than python.

Specifically relative to Ruby: at its core Ruby is matz's place to experiment about ideas in programming languages. If you are going to build your business around a few million lines of glue code that relies on the internals of a language, you want to have strong guarantees about the stability of what you're building on.

Looking back I think the python 2 to 3 transition period actually made this better for python by providing a very stable foundation in python2 while experiments and destabilizing changes were mostly pushed to 3, which kept ahead. When finally transitioning to 3, the needs of the scientific python community and ecosystem were so well known and represented that it was unlikely to simply get forgotten, left out, or left behind.

Pretty good analysis and recollection. Thank you.
Ruby was relatively unknown until Rails made it popular. Python had a head start.
Numpy was working fine and effectively for a long time, ruby had narray but it wasn't as good (less documentation and such). Then scipy was the same. Then pandas etc etc.
Looking at Tiobe, in the early 2000s Python was a lot more popular than Ruby although neither was very popular. Then RoR took off but that only made Ruby on parity with Python as Python's popularity was also growing. Or in other words, 90% of Ruby talk became about RoR while Python wasn't. If you're making a quick local program or library, would you pick the language where people only seem to do web dev or one that seems to have broader adoption?

edit: Which lines up with my recollection, Ruby was synonymous with Rails and web dev while Python wasn't type cast yet.

Ultimately, it's probably that Python is older and it's use in the English-speaking world is substantially older. Python is around 5 years older than Ruby and the first book about Ruby in English came 10 years after Python existed.

It's 1995. Python has been around for 5 years. Guido is working with the scientific community and adding better complex number, array, and matrix support to Python. Ruby has just started and everything is in Japanese. Scientists and Engineers at US universities and FFRDCs (Federally Funded R&D Centers) keep plugging away at Python for scientific purposes. Finally in late 2000, the first book about Ruby is published in English. Ruby is still pretty unknown. In 2005 Rails hits the scene and the English-speaking world notices Ruby. But this is 10 years after the scientific community starts investing in Python and 15 years after the Python language came out. By this time, the community had Numeric, numarray, and finally NumPy to unify their efforts.

Ultimately, Python's BDFL started working with the scientific/numeric community before Ruby existed. It would be 10-15 years after Python that Ruby would start making inroads in the English-speaking world and by that time there was already good numeric/scientific tools in Python. Scientific communities weren't looking to learn new languages for the sake of new languages. Many still just use MATLAB.

MIT hadn't switched to Python when a lot of this happened. I think it's more that Ruby wasn't widely known to exist until 2005 and was "brand new" to the English-speaking world then. Python had been plugging away at numerical libraries for a decade by then and NumPy (which had learned from previous numeric/scientific libraries) came out basically when Rails came out.

Once all these numeric libraries exist for Python, are you getting grad students excited to work on an open-source numeric system for Ruby? Are you getting FFRDCs interested in creating libraries for a language that's quite similar to Python without any significant advantage? How do you justify that work? How do you get people excited about it when the reaction of most users is going to be "we're already happy with what we've got"?

Rails burst onto the scene at a time when people were often unhappy with their tools. Rails was a breath of fresh air with clean separation of concerns and a lot of helpful stuff. This is back when Java meant XML sit-ups, C# was closed-source and this is before most of what the community knows today existed, Scala had just appeared, Python was still in the Plone/Zope era (remember when an object DB in Python seemed good?), PHP was pretty dominant but often ended up a mess and didn't have the same framework that Rails was offering. Rails offered something compelling and new which meant attention. Many other communities followed Rails - Django, .NET MVC, JAX-RS, etc. Still, Rails was there first and got a lot of mind-share.

Similarly, Python was there first in scientific/numeric computing and people haven't provided enough to compel people to move off it.

I love reading historical context around language use like this. Thanks for sharing.
Quite interesting, thank you!
I remember Python being fairly popular for quick work in research 10+ years ago. It was simple and easy to start with but not that different from the c/c++ which they needed for performant bits.

>It's very capable in terms of making DSLs.

Which is a double edged sword. Too many DSLs means you have to learn and remember a lot more to write code.

Numerical computation is generally done on scripting platforms - Matlab for instance.

After a few different options such as Octave, numerical computation in the free software space coalesced around Python.

The Python ecosystem - it's change and release processes (PIPs etc) - thorough API documentation - make for a good target language, over other languages that simply do not have that infrastructure.

I don't know what the state of Ruby documentation is these days for instance, but back in the day, it was simply incomplete.

One reason I can think of is, certainly early in the Ruby/rails days it was quite difficult to support/install ruby on Windows. Python was much easier to install and get going with so it maybe got a foothold just because more people had access to it.
Another reason is that in the timeframe where people might conceivably written these, ruby was going through the 1.X->2 transition with all the pain that entailed.

ISTM (supporting a system written in Ruby at the time) that a large number of the libraries were broken when used in concert with each other -- and that language experts knew how to monkey patch their way around these issues, but didn't bother documented these fixes.

I've been told that things are much more mature and stable now -- but that experience put me off the language.

These are pretty normal growing pains and one should ascertain for themselves if they are willing to shoulder the risk of using an emerging technology. That being said, some of the "break stuff and monkey patch later" mentality is still in the community's DNA.

I am not trash-talking that phenomena but I also found it off-putting and eventually moved away from Ruby/Rails after 6 years with them.

I remember looking at both Python and Ruby when I was getting into dynamic languages - this was the time when Rails just showed up, and Ruby was suddenly getting a lot of attention.

I vaguely recall that Python documentation was generally much better at the time, and especially so the parts on writing extension modules. With Ruby, it felt like the English reference docs were largely an afterthought - you pretty much had to get a book on it to get far, and the more advanced sections (like extensibility) were especially lacking.

I didn’t really work in Ruby during those times, but I do today. I like it, I find it a very “plain” language to work in. I mean plain in the beneficial sense, Ruby makes it easy to write boring code. It has too many bells and whistles, such as all the OOP doodads, but I try to avoid those and just write functions.

I don’t really find it magical, though if I spent much time working in Rails I probably would. But, there is Ruby without Rails. I recommend it, in fact.

As you yourself found out, writing in Rails is very different. You can go crazy with all the things happening without your knowledge. I liked the productivity that Rails gave me back then but it very often felt like that the expertise you get is the result of a series of traumas (a lot of "Why the hell did this thing change 0.5 secs later?! I didn't tell it to do that!").

I worked on 3 smaller projects with Sinatra and Sequel and it was worlds better.

Commercially speaking though, there aren't many Ruby job offers that don't require Rails.

I still occasionally use Ruby when I don't trust bash/zsh with a slightly more complex automation flow but outside of that I find no uses for it.

Elixir and Rust do it all for me these days. I know I am getting biased and I am not fighting it. I need to get jobs done and at certain point always searching for a new tool gets very unproductive, not to mention stressful and soul-draining.

How do Elixir or Rust help you with front-end/UI? It seems you would need at least Javascript and maybe more if you're going to produce mobile apps.
Elixir has LiveView, which can eliminate 90% of your JS by simply offloading frontend computations to the backend and utilising WebSockets streams to do it. It's pretty neat.

Rust, AFAIK, doesn't.

But you are right of course, if you want to cover the full-stack then JS is mandatory.

Hi draw_down, I believe you are shadowbanned on HN. Just thought you'd like to know.
Thanks but I am aware, and there isn't anything I can do about it AFAIK
Ruby could use a proper module system as well. Ruby's require evaluates Ruby code and changes global interpreter state. Python's modules are so much better. Javascript's require is so simple: a function that returns a module object.
As someone who codes in Ruby daily this is my by far biggest issue. Ruby's performance is pretty good (I do not use Rails or ActiveRecord) and while the state of concurrency is not ideal it is not really an issue in practice for me, but the lack of a proper module system forces me to invent unnecessarily long and convoluted names.
That would be a very jarring change. Ruby class definitions are executed to define a class. There is no way to statically define a class in Ruby. This is frequently used. E.g lots of Ruby libraries add class methods that are executed during the definition of a class to mutate it during definition. This is Ruby's alternative to macros.

As such, you'd gut large parts of the language if you stopped evaluating code on require.

Yep, but that's a post factum worry. It's not an inherent trait of being a dynamic language that automatically surfaces during its development. Ruby's creator(s) simply chose to do it like that and now, of course, it's too late to do any sort of revolutionary changes.

Hi btw! Just now noticed it's you. :) Was thinking to write you an e-mail very soon. Which one do you prefer?

Yes, of course it could have been done differently from the start, but as you say it's now impossible to change. Though my Ruby compiler project (that seems like it will take the rest of my life at this point...) would have been far easier if it was more static. That said, I think it's less of a problem in practice - most code does things that can be fairly easily statically determined and/or that isn't actually doing anything particularly nefarious to other classes. A lot of the worst abuses that are possible with Ruby are also things I've never seen done intentionally in the wild other than as examples, and where deprecating and explicitly breaking them wouldn't do any harm.

> Hi btw! Just now noticed it's you. :) Was thinking to write you an e-mail very soon. Which one do you prefer?

Sure :) Same old e-mails (also on my HN profile page).

Isn't the real problem that Ruby's "magic" a lot of the time relies on monkey-patching stuff?

I mean, Javascript's modules also are dynamically executed and then returned as a singleton module object (also cached, so only the first require actually runs the code before the module export). This means you can make a module which requires other modules and monkey patches methods inside them (this is how mocking actually works), wrecking havoc amongst all other dependencies, but library authors just don't.

The more in-your-face monkey-patching went out of favour many years ago. Most newer Ruby libraries make you explicitly "opt in" to changes by e.g. including a module and/or contain any monkey-patching in separate files that needs to be explicitly require'd if you want that behavior. It's rarely a problem in practice.
The code evaluation is not the problem. The fact all evaluation takes place in a single global interpreter context is the problem. When a file that defines a class A is required, the A constant of the Object class gets set to a new instance of Class:

  # a.rb
  class A
  end

  # irb
  require 'a'

  Object::A.new
All code evaluation modifies global interpreter state. Honestly it's not much better than the C preprocessor's #include directive.

A better design: files are always evaluated with a clean interpreter state and they can return values just like methods.

  # a.rb
  class A
  end

  A

  # irb
  a = require 'a'

  a.new
This makes all state local to each script by default. Users will only have access to the returned value which can contain anything or nothing. If a module needs to modify existing classes, they could return modules that can be mixed in or metaprogramming methods that perform the modifications when called with the targeted class as parameter. Perhaps existing classes could even be passed as parameter:

  require 'extensions', Object, Kernel
Of course, these changes would break compatibility with all existing gems. The result would be a completely different language that happens to also be called Ruby.
Most of the code that changes global interpreter state does so in predictable ways that are perfectly fine, so I don't think what you're suggesting would actually make much change.

Most modern Ruby code avoids monkey-patching "unasked" unless that is an explicit purpose of the project and using the gem is explicitly "asking for it" in the first place. Providing modules to include or making you explicitly call methods or explicitly require files documented to do optional monkey-patching has been the idiomatic way of handling it for years.

Adding the ability to explicitly provide guarantees that the required code is sandboxed might be useful and might particularly help tooling reason better about the code, but it would have quite little practical effect on most modern Ruby.

(comment deleted)
Yeah, having gone from Ruby to Python, it's a downgrade in most ways. Clumsy, ugly language.

But, man, the Python import system is so vastly superior to Ruby's "invisible distributed magic" way of handling the same thing.

The sad part is that there is no reason a good language could't have the good parts of both languages. But here we are...

> having gone from Ruby to Python, it's a downgrade in most ways. Clumsy, ugly language.

Python 3 is a much better language than Python 2. More consistent and much better designed.

I miss the Ruby standard library though. All those string, array and hash methods make things so easy. I often get stuck looking for Python equivalents.

> The sad part is that there is no reason a good language could't have the good parts of both languages.

There is: backwards compatibility. Most of the time it's impossible to fix a language because the result would be two different languages that have the same name. Python broke compatibility with version 3 and it is still competing with version 2 to this day. Ruby also did the same thing in version 1.9 but thankfully the scale was much smaller.

(comment deleted)
> It's readable...

when you start to learn a new programming language, you look up what people are doing. ruby let programmers write incomprehensible and unfriendly code. my experience is that it has been a huge turn off for beginners. there was a rush to make popular websites in the rails era, but that ended quickly.

as another example, cpp used to be a cool language to read and write in. they even taught it as first programming language. since then, they added some crazy stuff that made the language very unfriendly when put in the hands of some people. it is now very beginner unfriendly.

the syntax of python will remain a great inspiration for readability if they don't make the same mistakes. it always amazes me to see people from all levels read python the first time and get it.

> there was a rush to make popular websites in the rails era, but that ended quickly.

I so much want to agree with you here but I can't. 99% of all business people I've ever met are all about "Alright! We got the perfect idea! Let's have the first iteration done next week!" -- has been the sad reality of most of my bootstrapping conversations. Even if they aren't a young-ish enthusiastic bunch they still are going to go to whoever promises them the fastest delivered MVP.

IMO to this day Rails is a big winner in the MVP area -- although I will immediately agree that nowadays there are no small amount of other technologies that can give you a pretty good-looking and well-working MVP (mostly in JS land I think). But a lot of business people just managed to memorise that Rails is the way to go for MVPs. Their mind isn't easily changed. Now those several whom I talked with in the last 1-2 year were like "yeah yeah, you techies always chase the newest thing" -- and sadly they are often correct. So the hope of breaking free from Rails' "monopoly" on making MVPs looks pretty slim lately, to me at least.

I fully understand the business people's desire for things not to change often. But they vastly overestimate the viability of most of the tech out there. Or maybe it suits their bias. No clue.

>the syntax of python will remain a great inspiration for readability if they don't make the same mistakes. it always amazes me to see people from all levels read python the first time and get it.

Oh please. I like python and use it a lot, but it's readability can be awful.

Constructs like 'delimiter_string'.join( list_var ) may have logic behind them, but the readability for someone accustomed to OOP paradigms is backasswards.

Comprehensions are quite powerful, but ironically they're nearly incomprehensible.

Lambdas are a sad sad attempt at closures/anonymous functions.

There are many conventions in python made early on that have not aged well in regards to readability.

In my experience with Python, these were minor annoyances. The real problem was the amount of decorators and monkey patching in libraries like Flask, FoundationDB, Gunicorn, or Celery. Using gevent didn’t help...
I found Ruby a bit easier to read and much easier to learn than Python as a beginner. In fact, I'd say it's the most beginner-friendly language I've seen, especially with great resources like Chris Pine's Learn to Program.

If I had to rank learning difficulty I've found various languages, I'd say Ruby was the easiest one I've ever encountered. It's very consistent, everything is an object, it's flexible and you don't need to learn anywhere near all of it to become productive with it.

Python is fairly beginner-friendly too, but it's less consistent, significant whitespace leads to a certain class of mistakes that are maddening for a beginner and at least when I used it pip was nowhere near as nice to work with as gems and bundler.

Both are much easier than JavaScript or anything where you manage your own memory, though!

> the syntax of python will remain a great inspiration for readability if they don't make the same mistakes... it always amazes me to see people from all levels read python the first time and get it.

I think python had already crossed that bridge, at least for webapps and ml (albeit not at the syntax level). Consider what you must bring in for a real webapps deployment: virtualenv, uwsgi, celery, nginx, at a minimum, probably rabbitmq for many apps. Deployment is a nightmare.

For ml, you'll need to pick your library, version it correctly (some ml models are even firmly stuck in python 2.7), probably manage it all in conda if you are testing different models, since your source is bound to different tensorflow/pytorch/python/cuda version dependencies, and deployment is a nightmare.

Maybe I'm missing some python best practices due to the places I've been (django/angular shops that don't write tests) but ultimately I think this is Not very beginner-friendly at all.

I think the parent was speaking specifically about the language, not the ecosystem. More "if I open up this Python file, can I understand what it's doing," not "can I execute this application easily." I think Python is excellent at the former—Syntax is simple and explicit, "clever" code is discourages by both the language and the community.

Packaging is a known pain-point in Python and does make the language less approachable. But beyond that I don't understand your criticisms. uwsgi, celery, nginx, RabbitMQ are all useful tools that are oftentimes used in web applications. What language are you using that magics away the need for tools like these? All these same tools or their equivalent still exist in the Rails ecosystem.

I don't have much hands on experience with ML, so I guess I can't comment on that. Is there something about Python that exacerbates the issues you've laid out?

Eixir/Phoenix at least makes those dependencies go away, but some use nginx (I have) and you might use rabbitmq but only if you want to run a queue that other languages participate in.
We must be reading different versions of Python as the magic double underscore, weird bolted on OOP is in my opinion a lot more unreadable than some code golf rubiest go for.
Most of what you mentioned seems to be fixed by Crystal. That said I am not sure when Crystal becomes production ready or 1.0.

Not saying Crystal will be the silver bullet, as it will take at least one or two years writing a large codebase with it before we can make any decent judgement.

> That said I am not sure when Crystal becomes production ready or 1.0.

I don't doubt a lot of newer tech solves many lingering problems that are still present in older tech but that's the crux of the issue right there in your comment:

We work for money and we have to get stuff done in acceptable amounts of time. And our bosses want us to write with technologies they can hire for, in case we get fired or killed by a bus.

I can't speak for everyone but now, at 39, I already have a bit of a fatigue and burnout when it comes to trying new languages. I just want to sit down and fix a problem (or create a feature) without having to sift through a forest of competing tech for days or even weeks.

Please note that I am not berating Crystal in any way. I know absolutely nothing about it. I am simply unwilling to invest in learning my (I think) 9th language. Elixir and Rust do me pretty perfectly lately and this is going to be the case for a while.

"...too much magic and implied behaviour..."

This is why I opted out of Ruby. Feels too much like macros and C++ templates. I just don't want to be that smart.

I keep going back to Bill Joy's goal of enabling working both in the big and in the small at the same time.

Mid 90s, Java was logical step from C-ish towards Scheme-ish and Simula-ish (SmallTalk, Self). I could focus more on design and less on wrestling the compiler. Much progress since then, in Java and elsewhere.

But I wish language (and stack) designers also removed features. Cull deprecated stuff. More generalizations. Fewer primitives. Fewer classes. Etc.

> This is why I opted out of Ruby.

That was probably ~80% of why I opted out as well (the rest ~20% are mutability and bad parallelism story).

> Feels too much like macros and C++ templates. I just don't want to be that smart.

I don't even view it as being smart. It's more like a specialised area of expertise that you need to grind through in order to be productive, and even when you're an expert it's still error-prone. Turns out though, a lot of other tech doesn't require that so, like you, I moved there.

> I keep going back to Bill Joy's goal of enabling working both in the big and in the small at the same time.

Admirable goal. I try to do the same but it's not an easy thing to achieve. What language would you recommend in this area?

> I could focus more on design and less on wrestling the compiler.

Depends what you mean. I am very okay to fight with Rust's compiler because that way I know I won't have dangling pointers or references and will not inadvertently try to modify the same piece of data from multiple threads. I am also very okay with fighting with OCaml's compiler because I often found myself not thinking properly about the types of my code.

But in C and C++, yeah, there the fight is kind of just "please compile and leave me alone" and it's not that much of "it's compiled, therefore you get guarantees X and Y".

> But I wish language (and stack) designers also removed features. Cull deprecated stuff. More generalizations. Fewer primitives. Fewer classes. Etc.

Absolutely! I wish more language designers/maintainers had the courage to do this. They also don't have to do it in a breaking way; they can just extract the deprecated (and removed) functionality into an optional dependency that people can use if they are so hell-bent on not using the officially sanctioned way from version X.Y and on.

But I guess even that would catch many people by surprise and provoke negative reactions so it's probably a very strong reason on why it isn't being done.

So what's left? A linter that's invoked like this: `idiomatic-rust --check --strict`?

I guess that's the only way out for now.

"What language would you recommend in this area?"

I wish I knew.

For ages, I've imagined a Java do-over I code named Encore. What would "Java" look like today, given the same original goals of improving programmer productivity and reducing errors.

But now I've switched tacts almost completely.

TLDR: Code generation 2.0. Code you'd write yourself, if only you had more time.

So with SQL, for example, instead of a wrapper or model which generates SQL at runtime, start with the SQL and generate code (in your target language) at compile time.

I've done this, with varying degrees, for SQL, HTML, HTTP, HL7, DICOM. Just trying to flesh out the idea, strategy.

One consequence is the target language becomes much less important. So now I feel (hunch, as in "believe but cannot yet prove") that the smaller the language, the better. Like BASIC, Pascal, Lua (which I don't particularly like) small. Barely more than a scripting language with some objectness and modules.

And even more impactful, the contemporary libraries and frameworks become much less important, or even moot.

Thanks for replying. I'll post something if my efforts mature enough for sharing.

>But I wish language (and stack) designers also removed features. Cull deprecated stuff. More generalizations. Fewer primitives. Fewer classes. Etc.

Oh Hell yes. I wish they have plan for depreciation. Trial, > Warning > Error > Removed. Push the whole language and ecosystem forward. That is 10 times easier then going to a new languages and making new ecosystem.

> - He seems a bit disappointed that Ruby is mostly used for web development only and would be happy if it was used in research and AI.

Flowstone ( http://www.dsprobotics.com/flowstone.html ) uses Ruby for scripting, so there is a bit more to Ruby than webdev.

> He regrets not focusing on immutability primitives earlier.

Hah, I think every business-first (as opposed to academic-first) language had this problem.

Immutables are easy to implement in every OOP language but the if standard library isn't aware of them out-of-the-box you're SOL.

Never tried to make a programming language myself but what you say is interesting. I wonder if this mentality (mutable-first) can be changed at least in universities?
> is now working on an optional typing system where you choose to describe types in a separate file. (Reminds me of C/C++ and OCaml header files.)

My experience using C/C++ is limited, but this always feel felt rather cumbersome to me.

In C/C++ it definitely is. But it sounds Matz wants to do it similarly (but not exactly) like in OCaml, where the "interface" file only describes all public modules and functions and their typing signatures, which serves the purpose of (a) limiting access to the users of your modules/functions to only those you want to expose and (b) help the compiler's typing system.

Do note that in OCaml explicit typing is rarely needed. The compiler is quite amazing at inferring the data types of your functions. In Ruby though, it seems the typing definitions will be the front and center of those suggested interface/header files.

The global variables is generally mitigated by RoR but that leads right into one of his primary regrets that it's not used for something other than Web.

I'm sad to hear that he's sad about that because to me I love Ruby/Rails for the web. It's just too strong for getting off the ground for me to ignore. The community has solved so many problems that allow me to focus on business/user issues.

Not having static typing is that double edge sword. I personally wish it had it now as well having been with Ruby for 5+ years seriously. I've played with Sorbet, but in the Rails world, it's just too weak to be useful. Too many exceptions/untyped definitions to allow everything to play nice. It's the standard problem of trying to make an un-typed project => typed.

With all his gripes, the frameworks he laid down -> human readable + everyone be nice to each other has been incredible. The 1st one is controllable, but the 2nd relies solely on other people carrying it forward. Issues, forums, meet ups, conferences. It's not perfect by any stretch, still lots of issues, but it's incredible to see that the community does try and is relatively successful at it.

Even though I moved on from Rails ~3 years ago I am not spiteful of it -- I just came to realise it's just not for me. I am really glad the community is still going strong.

IMO Rails -- and Ruby by extension -- are going through its first really mature phases: a critical look inward and trying to solve problems that the initial enthusiastic wave of adopters haven't found crippling... but many people after them did.

That's a good phenomena and I like it. And I am one of those people thinking that Ruby and Rails both benefited and suffered a lot from the huge popularity burst that they got.

Now is a good time to start making positive changes and to make the language (and the ecosystem) more long-term sustainable and I am glad that Matz is thinking about it.

> But I never found good use of it outside of small projects. Any serious business work becomes very painful to maintain and stay on top of for bigger projects.

It's the ultimate irony reading statement like these, when ruby powers some of the largest web applications on the web today and handling millions of users and requests.

Github, Gitlab, Shopify, Stripe, AirBnb, Crunchbase, Dribbble, Kickstarter, .. etc

I'm not sure how many more are needed for this meme to die. Is ruby perfect? absolutely not, but to neither is any other language. You will always have to tweak things regardless of the tool you chose, because scaling is difficult.

> You will always have to tweak things regardless of the tool you chose, because scaling is difficult.

With some technologies, like Erlang/Elixir, scaling is almost effortless though. Only the deployment platforms with very strict boundaries like Heroku make it pretty much impossible to shard and distribute load. With most VPS-es you just share one file between them, introduce a well-setup VPC, and you're done, your servers are distributing load and you spent like an afternoon on it.

Additionally, with very fast languages like Go and Rust (even Elixir but only on I/O bound projects, which is like most of them?) you delay your scaling measures that far in the future that most apps never even need to grow beyond one app server and one DB server, and the team never actually even thinks about scaling at all. Because let's face it, most apps will never exceed 500x - 5000x reqs/sec. A well-made Phoenix web app or API gateway easily achieves 500 reqs/sec even on a Raspberry Pi 4.

I used Rails for 6 years and deployed it on Heroku, company-rolled Dokku setups, AWS EC2, DigitalOcean droplets and GCP -- usually servers in the range of $25 - $100 per month (I usually work for small or medium-small businesses). I hated that beyond 10-20 reqs/sec we had to start beefing up the server or add others. It's just how Rails (or rather, ActiveRecord) is: very inefficient, optimised for human productivity, and to hell with machine resources. Many business still like it though and that's cool with me. They don't mind a mean response time of 300ms with the minority of responses (95-th percentile) going to 2500+ ms.

> Github, Gitlab, Shopify, Stripe, AirBnb, Crunchbase, Dribbble, Kickstarter, .. etc

I wish for that meme to die. Bigger players using it means absolutely nothing except that they have the budget to keep working with Rails even after it showed its warts (hard to maintain when the project grows and big hosting costs being the top 2).

Smaller players like Basecamp have very stringent policies on how to work with it. I've seen local companies utilise similar techniques mostly successfully. More power to them. I know it can be made to work with the right management techniques.

Half-related: do remember that Facebook preferred to make a PHP runtime and maintain it, as opposed to actually train programmers to use another backend language.

> I'm not sure how many more are needed for this meme to die.

You might call it a meme. I call it "I tried for years and eventually got frustrated and moved on".

Nothing against Ruby or even Rails. But they make me think of scalability much, much earlier compared to a "slow" dynamic language like Elixir (even though it maintains predictable lag even under very heavy load... and its Phoenix framework mean response time in identical setups as the Rails projects is between 5ms to 30ms).

Let's not even introduce Go or Rust web apps in this picture. If made well (although that takes much more effort than Rails or Phoenix so for me their human productivity tradeoffs aren't worth it!) they can easily serve anywhere from 5_000x to 30_000x reqs/sec on the cheap business VPS-es ($25 - $100 a month). In all fairness, those had to use a bit more expensive DB servers though ($250+) because the cheaper DB servers couldn't keep up with the demand.

> But I never found good use of it outside of small projects. Any serious business work becomes very painful to maintain and stay on top of for bigger projects.

That statement reminds me a lot of the conclusion I came to on a reddit post[1] a while ago, where I compared Rubys fibers¹ to Luas coroutines, more specifically, how many of them could viably be used concurrently:

> Conclusion: Ruby is awesome; just don't use it for anything serious.

¹ Note that after Ruby 2.7 was recently released with a supposedly improved coroutine implementation, I repeated the benchmark and did see a slight improvement in execution time (no change in the maximum number of coroutines), but it was still orders of magnitude slower than even the PUC Rio implementation of Lua.

[1] https://www.reddit.com/r/lua/comments/cgqfch/lua_coroutines_...

> Conclusion: Ruby is awesome; just don't use it for anything serious.

LOL! Funnily put.

This did offend some in this here mini thread but I indeed gradually -- with business and personal usage -- came to that conclusion by myself.

Nowadays I am pretty hopelessly hooked to Elixir. Parallelism and concurrency basically solved, extremely fast for a dynamic language, FP, compile-time macros (so basically code generation without the boilerplate source code), several very solid and customisable frameworks (web/API/GraphQL, DB data mapper), predictable lag even under extreme load, and I am just in love.

Now only thing left is Rust to emulate the BEAM's runtime. :)

If we were to have a vote for a language with which you replace a slightly more complex bash/zsh scripts however, I'd vote for Ruby. It's very terse, it's fast enough (without Rails I mean) and it mostly reads well. Or I dunno, maybe Tcl/Tk or OCaml.

> too much magic and implied behaviour

I think you may be confusing RoR with just Ruby.

Rails is its own beast.

I didn't confuse anything. I specifically mentioned Rails before listing those drawbacks you quoted.
We’re thrilled that our good friend Yukihiro Matsumoto, creator of the Ruby programming language, has been able to join us at RubyRussia 2019 as a speaker for the second time, having previously spoken three years ago at RubyRussia 2016.

In the time that we’ve been holding the conference — now more than ten years — Ruby has undergone a great deal of evolution, and Evrone has grown and developed alongside it.

Grigory Petrov, Developer Relations at Evrone, sat down with Mr Matsumoto to hear from him first-hand about being a star, the philosophy behind Ruby’s design and evolution, and a little about Japanese life and culture.

I don't understand languages like Ruby and Perl and their supposed emphasis on "human design." My sense of what a human designed language would be is a lot more like Scheme: extremely simple, fundamental abstractions which, when composed, enable a variety of different strategies for solving problems.

Ruby, in contrast, seems like an absurdly complicated concatenation of weird features and strange syntax. When I look at Ruby my eyes glaze over with all the unnecessary syntactic doodads and peculiar abstractions. Why anyone would want to complicate their lives with all that silliness is beyond me.

And yet Scheme languishes and Ruby, for a time, anyway, burned brightly. I'm clearly the weird one.

> I don't understand languages like Ruby and Perl and their supposed emphasis on "human design." [...] Ruby, in contrast, seems like an absurdly complicated concatenation of weird features and strange syntax.

Sounds like a human (natural) language to me ...

I had the same thought. "Simple" does not mean "easy" and "for humans" does not have to mean simple.
I can only recommend the "Simple Made Easy" talk by Rich Hickey.

I suppose it can be said that Scheme is very simple but hard for many, while Ruby is very complex but easy for many.

I think Rails fits what Hickey says about easy complexity very well. Ruby not at all - I find it very much not “braided together” compared to other programming languages. It’s still object oriented, and Hickey’s talk is largely directed at showing how bare maps and immutability and functional style and so forth in Clojure are better than what he calls the “petty parochialisms” of class hierarchies. But among OO non Clojure languages I’d argue Ruby is among the closest to th ideals he espouses in that talk.
Now I love Scheme but I would argue the exact opposite for the same reasons you listed. Scheme (Lisp, actually) is so simple and so cohesive that it feels like it was given to humanity by an advanced alien race.

Languages like Perl, on the other hand, feel right at home with the English language. There’s a deep history of all these different things from many different places that have been bolted on over the years. It’s incredible that we can say anything at all, let alone write amazing works in it.

But once you learn the alien language you can understand all written forms in that language. When you speak of Perl, which dialect of Perl are you speaking of? I'm not singling out Perl here as I see the same issue in varying degrees with most general purpose languages.
>Ruby, in contrast, seems like an absurdly complicated concatenation of weird features and strange syntax

My experience is the precise opposite. Ruby seems more consistent and straightforward than any other non lisp language I’ve used. Ubiquitous blocks and “everything is an object” gets you very far.

Compare nested list comprehensions in python to chained map/select calls in Ruby:

lesson for lesson in [school.Lesson(downloaded) for downloaded in api.downloads()] if want(lesson)]

vs

api.downloads.map{|download| School.Lesson.new(download)}.select{|lesson| want(lesson)}

Or compare the many varied required ways to do something with an array in python vs Ruby:

len(array)

“;”.join(array)

array.append(x)

Vs

array.length

array.join(“;”)

array.append(x)

Genuinely confused what you refer to with “unnecessary syntactic doodads.” Examples?

You answered your own question with your qualifier... "Ruby seems more consistent and straightforward than any other non lisp language I’ve used."
If OP just meant ruby is syntactically complex compared to lisp, there’s really no arguing with that! :-) it just applies to so many languages — any non lisp — and seems an odd thing to single out Ruby for. (Perl, on the other hand...)
He has replied with actual code samples. Which is valuable.
Both sets of code samples look silly to me. In scheme all this syntactic nonsense would just be function calls and lambdas.
Beauty really is in the eye of the beholder, because I agree fully with parents' statements. Then again I write Ruby for a living...
> lesson for lesson in [school.Lesson(downloaded) for downloaded in api.downloads()] if want(lesson)]

You could do filter(want, map(school.Lesson, api.downloads()) in Python.

This works until you have to pass additional arguments to `want` and `school.Lesson`, then it gets very messy very fast.
> Ubiquitous blocks and “everything is an object” gets you very far.

Blocks are not objects. So much for "everything is an object". At least, this is my understanding, I may be wrong?

They are converted to procs and you can pass them around just like anything else.

  def foo(&block)
    puts block.class
    block.call
  end

  foo do
    'bar'
  end
> My sense of what a human designed language would be is a lot more like Scheme: extremely simple, fundamental abstractions which, when composed, enable a variety of different strategies for solving problems.

“Human design” isn't “human designed” but “designed for humans”, and, more specifically, “deidned for the way human brains naturally work” rather than “deidgned for ivory-tower ideal of how brains should work”

> Ruby, in contrast, seems like an absurdly complicated concatenation of weird features and strange syntax

And, in that respect, is a lot like natural languages, which are quite often complex analytically/descriptively, with near-duplicate features, leveraging implication, etc., etc., etc.

As someone who studied the game of Go for a bit, simple rules can be deceptive. You can get whole bookshelves of books about things with rules that are too simple.

“The Rules” that matter become the patterns that the simple rules allow or imply, and all the nuances of when one is better than another.

> My sense of what a human designed language would be is a lot more like Scheme: extremely simple, fundamental abstractions which, when composed, enable a variety of different strategies for solving problems.

Consider the natural human languages- they're far from being straightforward uniform compositions of extremely simple abstractions. They have weird syntax, and a lot of redundancy.

Now, some of it is historical legacy, but not all. The language doesn't just have to be easy to analyse semantically - it also has to be easy to parse. And while parsing identical nested brackets is easy for a machine, humans prefer more variety for their pattern matching inputs.

My impression is that human languages are more expressive - There is more than one way to do it.

  # For a bank,
  if ($authorised) {
    allow_entry();
  }

  # vs. a shop:
  allow_entry() unless $person->is_smelly();

The language lends itself to how you may normally say it in English, emphasizing the common case. That isn't to say all the syntactic noise is justified, but I guess one's noise is other's attempt at being more expressive.
Shit, he should have considered the human cost of method_missing.

Yes, I am serious, it’s a massive productivity drain. You encounter methods that you can’t google for, so your grep game better be good to get work done (grep for a portion of the name, and then method_missing itself if that fails). An IDE is useless in this case and your performance goes out the window. It’s much better to dynamically generate a finite number of methods you can see when inspecting objects.... I suspect those would jit better, too.

Oh, you want to access the call stack on your server to figure out where that frame is? Jokes on you, ruby has no remote debugging mechanism aside from a core dump or building your own heap inspection access.

Dang, why was this flagged?

Reminds me of ''Programs are meant to be read by humans and only incidentally for computers to execute'' from Structure And Interpretation Of Computer Programs.

What always gets me about that quote is that's it's obviously false. There are exceptions (such as space shuttle controls), but most software that's ''important'' is important because of how much it's run --Firefox is run a whole lot more than it is read-- and so this Incidental Execution stuff is nonsense.

Performance and Readability are both important goals. Most of the time they're not even opposed as to justify pitching them against one another like this.

I was a RoR developer for two years and immensely enjoyed coding in Ruby, well technically, RoR(Ruby on Rails). It was in a startup and features were being developed at a rapid pace and it really felt like the right choice. But I also noticed that as companies grow they have problems with the maintenance of the code as well as the performance like twitter moving away.
Dear everyone crapping on Ruby (and esp. Rails) in this thread (and every other time this comes up),

If you don't like Ruby or Rails, that's okay!

No, really. You can use something else. You won't hurt our feelings! Programming languages and their frameworks can actually be a preference, not a moral issue.

We're here because we like it, and it's totally cool that you don't! Please use what you love; we are, and we know how powerful that can be.

Cheers, — Every Ruby Developer

I'm seriously not able to distinguish how many of these comments are about Ruby and how many are about Ruby on Rails (RoR). From the very beginning Ruby's popularity and criticism have hinged on RoR. And most people tend to conflate the two completely.

Personally, I love Ruby but don't like RoR. RoR seems to bloated to me. Of course it does many things. But very rarely have I come across projects which require all those things. And even then, I'm quite sure, we wouldn't be able to use all that RoR has to offer.

For many, many, years now, my stack has been Roda / Sinatra for routing and Sequel for DB access. And whenever, we've come across some requirement which needs heavy lifting, there are enough Ruby gems which do that without tying you up with the RoR framework.