Python's Caduceus Syndrome
vicki.substack.com
vicki.substack.com
I do understand the appeal; I think its ergonomics are exemplary and worth being studied by language designers as a success case (if not a perfect or unique one).
Going forward, though, I'd like to see more adoption of languages like Nim, Kotlin, or Julia, that have similar levels of expressiveness but are more performant. The issues discussed in the article aren't really growing pains; they've been there from the beginning.
In quant finance, for example, once the research quants have developed a strategy (in python or matlab usually), the professional developers have the thankless job of actually implementing it in C++ or whatever.
I agree.
Python is an awesome high level interface to low level libraries and algorithms. As which it became even more appealing since you can write your low level code in Rust and call it from Python via PyO3 [0].
All that said, lots of people I deeply respect love the language and I think it ultimately just comes down to some different wiring in our brains about what intuitively makes sense or doesn’t.
Interesting, what inconsistency? My understanding is that the main interfaces the language provides (Sized, Iterable, Container, etc.) are defined in terms of dunder methods that are used by top level functions (len, iter, sorted/reversed). Granted, the python-of-1995 decision that objects like dict or list shouldn't have chainable methods is weird compared to modern ergonomics (like streams), but that decision predates a lot of those practices by decades.
> The special self param you are forced to add to method specs so that they don’t match how they are called.
Is this more, or less magical than a `this` param that is magically accessible in method bodies and references something, though it's not always clear what, especially in the case of nested classes/scopes (Java/JS)?
> The weird and unexpected rules about how to interact with multiple kinds of strings (what?)
Huh? Do you mean unicode/bytes? This isn't really hard. Just use unicode everywhere unless you're dealing with something that is conceptually either a bitstring you're going to do bit-twiddly things to, or an opaque blob of bytes.
> Interesting, what inconsistency?
Sized is an interface, exposed via a function. String is a type, which has methods. Now yes, you can make an argument that everything is an interface ("upper-able"). But bleh, and this avoided problems like "is it .length or .length() or .size or .size()" as happened in some other languages.
"".upper() vs len("")
The first appears to be an object oriented language such as Ruby or Javascript.
The second appears to be some language with plenty of static or built-in functions, such as PHP or C.
This is clearly inconsistent under any definition of inconsistent.
upper([1,2]) (so `upper` is a static builtin) or being unclear on whether its "".len or "".length or "".size or "".size()
Like I said, there is consistency: interfaces are given top level things (builtin functions, operators, language features/keywords), while object methods don't.
To give a recent anecdote, Rust's `x.await`, which is more "consistent", but everyone is complaining because in most languages async interfaces are exposed via something like `await x` instead of an attribute/method-y thing.
That statement... first, there isn't any evidence this is true. For the Instagram example, if you're that big, you're going to have scaling issues, but it's an incredible position to be in. I've seen Java GC issues at large scale. That's the price you pay for GC.
That is to say this is a feature, not a bug. CPU is cheap. Productivity is hard. C code can be slow if written badly. Obviously Python isn't without it's trade-offs, but to imply it isn't suited for long-term, stable projects is incorrect.
It takes time for developers to learn a new language. Who's to say they wouldn't have made similar mistakes in other languages?
Again, course there's a trade-off, and Python isn't without it's flaws. But to pretend another language would have solved everything - development doesn't work that way. And scaling issues are a sign of success. You might not have made it that far with another language.
So pick wisely, and build stuff, and remember the choice isn't final.
It's not specific to Python. Big projects written in dynamically-typed languages are hard to reason about and maintain. And the lack of compiler makes it harder to catch typos, incorrect types, non-handled null/None values, etc… before runtime.
linters exist for a reason. it isn't so clear-cut any more, either, with type hints in python that can now be enforced, although honestly i haven't experimented with that much, since i don't think it's necessary.
> Big projects written in dynamically-typed languages are hard to reason about and maintain.
let's not pretend statically-typed languages are always easier to reason about. throw enough interfaces into a Java project or templates into a C++ project and they're also hard to reason with.
you may have had bad experiences with dynamically-typed stuff, or simply prefer static typing, but these seem more opinions than facts.
and again, i'm happy to argue that it's hard to predict the future. many projects benefit more from the increased velocity dynamically-typed languages offer at the start (the exploration if you will), than trying to build a system for millions of users from the start. that probably makes sense for FAANG projects, but for most it's overkill. so the suitability towards "long-term, stable systems" is half true. hindsight can be powerful, but can also be misleading.
As an aspirational Rust-learner (well, I've read the first chapter of the book) this is spot on. :P