top | item 41573567

(no title)

commodoreboxer | 1 year ago

I agree with you, and I'll put it slightly stronger. Ruby is a better language than Python in every way except the very most important two:

- Imports in Ruby seriously suck compared to Python. Everything requires into a global scope and an ecosystem like bundler which encourages centralizing all imports for your entire codebase into one file.

- Python has docstrings encouraging in code documentation.

Add common ecosystem things like the Ruby community encouraging generated methods, magical "do what I mean" parameters, and REPL poke-driven development, and this leads to the effect that Python codebases are almost always well documented and easy to understand. You can tell where every symbol comes from, and you can usually find a documentation entry for every single method. It's not uncommon for a Ruby library, even a popular one, to be documented solely through a scattering of sparsely-explained examples with literally no real API documentation. Inheriting a long-lived Ruby project can be a serious ordeal just to discover where all the code that's running is running, why it's running, where things are preloaded into a builtin class, and with Rails and Railties, a Gem can auto insert behavior and Middleware just by existing, without ever being explicitly mentioned in any code or configs other than the Gemfile. It's an absolute headache.

My dream language would be Ruby with Python-style imports and docstrings.

discuss

order

Myrmornis|1 year ago

I think your comment needs to mention that Python has syntax for type annotations and two mature type checkers (mypy and pyright) with more under development. Python is thus very much part of the modern statically typed languages scene (moreso than Go) whereas Ruby isn't at all. Many people wouldn't touch Python today if it weren't for this.

pansa2|1 year ago

> Python is thus very much part of the modern statically typed languages scene (moreso than Go)

Python’s type system is substantially more complex than Go’s - it’s probably more complete, but given it’s optional nature, less sound.

In “modern” type systems, is completeness considered more important than soundness? The success of TypeScript suggests it is.

pansa2|1 year ago

> two mature type checkers

I’ve never quite understood how this works. Surely a type system is absolutely fundamental to a language - how can you have multiple incompatible ones?

Do you need to choose a particular type checker for each project? Are you limited to only using third-party libraries that use the same type checker?

RMPR|1 year ago

> syntax for type annotations and two mature type checkers (mypy and pyright)

I would throw Pyre in there too

antod|1 year ago

Hard agree on the global Ruby import issues. I remember inspecting large custom Rails or Capistrano codebases in pry and having thousands of names imported. That and monkey patching had me wishing for Python with imports only having module scope and being a lot more explicit.

nextos|1 year ago

It's a shame Python has a strong anti-FP stance with crippled lambdas. And an OO system that looks like it has been bolted in, compared to Ruby which is essentially a Smalltalk with Perl-like syntax and some Lisp influence.

These two issues would have been quite easy to fix and would have led to a completely different development experience. Python had a good implementation with a nice C FFI (CPython) right from the beginning, whereas Ruby MRI had lots of efficiency issues with long-running computations. IMHO this is one of the reasons why Python won. Building a numerics stack on top of MRI did not look very promising.

pansa2|1 year ago

> an OO system that looks like it has been bolted in, compared to Ruby

I think the two languages just have different design philosophies. In Python, functions are fundamental and classes are built on top of them. In Ruby, objects are fundamental and functions (i.e. Procs etc) are themselves objects.

You could just as well claim that in Ruby, functions look like they have been bolted in. For example, you can’t call a Proc itself but need to call one of its methods.