I would revise that to be that to be that the pythonic culture of one acceptable way to to is better matched with a lot of good development practices.
Perl was also very good at finding a Perl way to proceed. It's just that with Perl that often mean a lot of implicitness and "do what I mean", and multiple ways to do it so you could fit it within your preferred style and tailor it to the current project's needs.
That all sounds good until you are confronted with the flip side of the coin, which is that it's harder to understand when looking at something written with those perspectives for the first time or after a long hiatus from the project, which puts a lot of importance on policy and standards which saps effort from just getting something done.
I love Perl, and it's still the language I write most often for work, and it's no great mystery why Python became preferred.
Would mypy with pydantic be a good combination or do they overlap?
Pydantic overlaps with mypy in the sense that it provides a mypy plugin, but otherwise it's just like any other Python library.
Those other things you mentioned aren't relevant to tooling. They're distributions, libraries, and applications. But note that Conda's existence was basically due to the fact of Python's tooling being poor.
I began in that world view. The C/C++/Java/DotNet everything must have a standard, a fixation on a singular consensus. That's not how things work in the open source world of Python, javascript, rust, etc. Will there be gravitation towards a paradigm? sure, until such time that a new one emerges.
If you looked at Python in the 2.5 days and looked at Python today - You cannot argue the tooling has gotten better.
That doesn't surprise me.
I do what you mentioned with F# in Polyglot Notebooks (which support several languages in the same notebook) and Elixir in Livebook all the time, both of which are superior notebook implementations to the outdated Python Jupyter notebooks.
My worldview is not driven by comparing Python to C#, Java, C++, and other such ilk.
Python had a great community though, and the Python Software Foundation went out of it's way to make people feel accepted in the community. And frankly programming is often more of a social activity than most people realize -- particularly for new programmers.
So new programmers tended to lean towards python, because the resources to lean on others were there. And people like Raymond Hettinger, Naomi Ceder, Ned Batchelder, and Yarko Tymurciak were approachable even if the BDFL wasn't.
Looking at the hip n cool languages, not just Python for scripting but surely Go and to some extent Rust as well for native stuff (Dart for scripting also but it didn't outright "win"), these are mostly languages that deliberately simplified things. Yes, even Rust - it needs to be compared to C++ and its biggest feature is basically that it doesn't let you do all the things C++ does, within a very similar model.
The only language that I heard is going against these trends (but I'm largely clueless what it's actually like) is Julia which sort of has its own "lay" niche like Perl did back in the day, and is mostly winning based on the premise that it's a performant scientific language.
The industry obsesses over costs of adoption, stability, maintenance; in short: how to get the most out of the least actual new development. It does make quite a lot of sense, to be honest, although sometimes it's really demotivating at an individual level.
And frankly, "learn the language, duh" usually comes up when the language is complex or unintuitive for no practical purpose. Of course there will be people who always complain if they have to learn anything but I don't think they make the majority, or even a significant minority, in the software engineering world. "Learning the language" is only as much of a virtue as the language itself serves its purpose, which includes easy of use and the readability of someone else's code.
Back then, the python jobs were scarce -- but based upon how I picked up the language, many of the typical C++ issues just disappeared -- and I knew it was going to become popular.
One comp sci professor talking at a PyCon years ago made a point that maybe the best college level introductory course probably should not have been SICP based but Python. His example was that for the first time in 5 years of teaching intro courses he had people coming up to him looking to change majors.
Fight me.
and https://www.johndcook.com/blog/2009/03/26/mit-replaces-schem...
and https://vimeo.com/151465912#t=3577s
As to being 'near impossible' to teach SICP with Python: https://web.archive.org/web/20210916151732/https://doc-04-5g...
We have all the cool kids like Kotlin, Rust, etc.
However, when it is about finishing a project, beating C++ or Java ecosystems is almost impossible.
Besides that, C++ has improved a lot over time. It still has its warts and knives but you can code very reasonable C++ with a few guidelines and there are also linters, and -Wall -Wextra -Weverything -Werror. That takes you quite far in real life provided you have a reasonable amount of training.
I would choose C++ over Rust any day. The only hope I have for C++ successors are Cppfront and Carbon and they are highly experimental. As successors those two fit the bill.
There is a third one, my favorite. It is this one: https://www.hylo-lang.org/ but I am not sure how compatible it will/would be.
not having to explicitly remember `free` in safe Rust code is amazing. Knowing that if my types are sound that memory will be managed reasonably is great.
I also think that immutable by default, mutable by explicit declaration is pretty great.
I do think there is a lot of room to add better ergonomics on these ideas however
Besides that, in real life you end up having C in most of your software, so I am not sure how Rust behaves compared to well-written C++ with all warnings and linters on and using smart pointers. But my hypothesis is that they do not stay very far apart in safety.
There are many ways to achieve safety, and the most promising, IMHO, is the path that Hylo programming language is taking. It sticks to Generic programming and mutable value semantics.
The language base draws from Swift and it has very strong people behind that know what they are doing. For example David Abrahams and Sean Parent. This is an implementation in a language of many of the ideas from "Better Code" from Sean Parent. It has a very solid foundation.
Besides being a solid foundation for generic programming, value semantics, and concurrency, what I like the most is how much it simplifies the model by not escaping references all around and preventing unnecessary copies. This removes the (IMHO) mess that is to have to manage reference escaping constantly in Rust, reason why many patterns such as Linked lists are not even possible.
And Lists are not just an academic exercise, as I was told sometimes by Rust proponents. Linked structures (Inmutable linked structures actually) are important in scenarios such as TelCo backend where you need replication, fast moving of data and history versioning, rollbacks and so on.
Being able to offload all that busy work to the type system is just nice. There are definitely ergonomic improvements that could be made around this.
All the rest? I'll leave that to someone else to talk through, as I'm no expert here.
It disallows many valid patterns. That is why I recommend to take a look at Hylo programming language (before called Val lang) to see what I think it is a very good example of how to make a language safe without making the learning curve so steep and without a need for a GC.
It's difficult to have this discussion in any sane way when Rust (or C) comes up. I tried Rust, but I have projects to deliver on strict timelines and I have yet to find a client who is prepared to pay me for the (what I found to be) very large onramp time to gain deep Rust expertise.[1]
The argument of "just get gud" whenever you point out the deep learning curve of Rust is pointless; I have noticed that Rust experts only come when your employer is rich enough to pay the team to not deliver while they learn it: Basically only FAANGs and startups flush with VC money.
[1] When I have a small project I reach for C. When I need something bigger for which C is not suitable, I don't reach for C++, or Rust, I rather take the tiny performance hit and move to Go. On extremely large projects, where I work with others, C# and Java seem to hit the sweet spot.[2]
[2] Although, C# and Java are also getting a bit too complicated for my tastes too. Seems to me that every language follows C++ evolution towards complexity, because the people stewarding the language are experts in that language and/or in programming language theory.[3] They are comfortable with the changes they propose because they have no need to upskill (they are already at that skill level).
[3] I propose that a language designed by your average corporate developer who has 15 years of experience but not CS degree will have much higher adoption than languages designed by PL purists.
Because I said:
>> C# and Java are also getting a bit too complicated for my tastes too.
I abhor complications.
> And why not go for the large projects?
Because I said:
>> where I work with others, C# and Java seem to hit the sweet spot
Yeah yeah, I know it sounds like I am whining (Maybe I am :-), but at least I am complaining about all of them.
Java and C# do appear to have been battle-tested for very large projects that aren't microservices.
Go? I dunno. I've only ever seen very large projects in Go using microservices. I like its simplicity.
My main complaint is that programming languages have too much minutiae to track that I really shouldn't have to be tracking.
Take, for example, asynchronous builtins:
Why are all the explanations wrapped in jargon that only an expert in the language would grok immediately? Promises? Futures? You gotta explain those, with examples, before you can explain what to do with a value from an async call. Go look at the popular introductions to async (say, on MDN for js, or Microsoft for C#, etc) and count how many times they have to explain something because of their leaky abstraction implementation rather than explaining the concept.
How about simply saying "calling async functions only schedules the function for later execution, it doesn't execute it".
That naturally leads into "So you need to check if it is finished using an identifier to identify which scheduled call you want to check"...
Which itself naturally leads to "The identifier you need was given to you when you scheduled the call"...
Which leads to "Using that identifier from `id = foo();`, you wait for the result like this: `result = id.wait()`".
You can even add "You can return that id, or pass it around so some other code can do `id.wait()`".
Now they don't explain it this way, because their implementation(s) is more of a leaky abstraction exposing irrelevant information about the compiler, than of a straightforward implementation of the concept. They are unable to separate the concept from their implementation.
The common implementation of async is so counterintuitive that they have to explain their particular implementation instead of the concept, because it has almost nothing to do with the concept. If they just explained the concept, programmers would still be confused because the implementation needs things like colored functions just to work poorly.
The concept of scheduled functions (which may return once, or may yield multiple times before returning), which is a simple path to understanding asynchronous calls, is completely divorced from the implementation which will produce errors like "cannot call asynchronous function from a top level"[1] or "cannot call await in a function not declared as async".[2]
So, yeah, I'm kinda upset at how programming has evolved over the years (I wrote my first program in 1986, so had a good seat for the later part of this particular movie), from "simple and straightforward", to "complex for complexities sake".
[1] Why? Because their abstraction is an abstraction of their implementation, and not an abstraction of asynchronous calls.
[2] Se [1] above.
This is not always true.
Can C++ compilers + linters reliably detect all misuses of unique_ptr? Because that sounds like a halting-problem kind of problem, and as soon as you can't guarantee memory-safety, you're definitely not in the same ballpark in terms of safety. I mean, memory-unsafety is the number one vulnerability cause in software. C++ has many qualities, but safety certainly isn't one of them.
Is C and assembly the same level of memroy safety? Probably yes... but no, it is not in practice.
And C and C++? Yes, in theory, in practice... C++ is safer.
How about Rust? In theory Rust is safer. In practice, you are going to use C libraries here and there, so... in practice not as safe as advertised.
Well-written C++ with -Wall -Werror, -Weverything, -Wextra... that is very safe, including detecting even dangling stuff. If you stick to `shared_ptr` and `unique_ptr` no matter how much you complain about it: Rust with its C shims and C++ with all linters and a good environment are practically at similar levels of safety.
This is the practical, real thing that happens. I do use C++ for every day use for around 14 years professionally and 20 years in total.
You are all in the terrain of theory, but how much Rust and C++ have you really written?
Of course, the CVEs data about memory safety, well, those are true. And they are a real problem. But with a reasonably good use of C++ those would be much, much, much lower than they have been so far.
Yet, somehow people do this with python, perl, and ruby. Google hires professional python people too.
https://charliereese.ca/y-combinator-top-50-software-startup...
C++ gives more return when you start to save in infra because you have a more efficient language, if coded properly. Same goes for Go vs Python.
The right tool for the right job. I would use (and will, I am on it) Django for a SaaS that I have for the backend. If things start to work relatively well, then, I will keep identifying, if there are, bottlenecks and migrate with a hybrid architecture parts of the workload to C++.
This allows me to save in infrastructure bills.
IIRC, Val has been mentioned on HN sometimes earlier.
I remember trying to compile GTK+ on a solaris system a decade ago, and remembering how terrible it was to even to get it to compile.
You're really deluding yourself if spending your time in compiler dependency hell is so much better than python.
I see this argument a lot, but people often forget that Python is very concise (yet readable) compared to other languages.
100k LOC in Python typically contains way more business logic than C++, so it is only natural to be harder to maintain.
i saw this linked on here recently: https://wizardforcel.gitbooks.io/sicp-in-python/content/
I can't confirm his thoughts on Perl and I haven't interacted much with Ruby, but the Python community is definitely welcoming and patient in my experience. I wouldn't be surprised if this was a significant factor in Python's prevalence over Perl, Ruby, or anything else.
(I write mostly Python these days, but have been involved in both communities for a long time, and MINASWAN never particularly stood out to me other than as a cute reminder to be nice.)
My interactions with Guido haven't been awesome. But the people put up with him regardless. The other people in python have been awesome.
TBH, community had nothing to do with Python's enormous success over its competitors (Perl, and Ruby. Possibly Tcl too.).
Nor did any technical merit, nor ergonomics.
There's one, and only one, reason why Python exploded at the expense of the other competitors: The ease and acceptance of using the language as glue for C functions.
Python's popularity is built on a solid foundation compatibility with C.
If, in the 90s, C++ had taken off enough to displace C, I doubt Python would be as popular as it is. Python owes its ubiquity to C, because if C was not ubiquitous, Python wouldn't be either.
(It's only recently, like the last 10 year or so, that I started seeing popular Python programs which didn't have a dependency on C libraries. And even now, it's still rare to see).
My experience of trying to get my own C functions to use in Python to have been nightmarish. Yes, you can do it... if you have exactly the same compiler & version used to produce the python interpreter itself.
C's only usefulness to Python is: it allows optimization of the 80/20 or 90/10 rule, so performance doesn't have to totally suck with Python.
Python 'won' IMHO because it hit a sweet spot -- simple enough for beginners, in fact, beginner-friendly, but due to having a good basic set of datatypes (lists, tuples, sets, plus the usual ints, floats, and complex) -- this allowed complex ideas to be compactly expressed. The ability to switch between functional and imperative styles also helped.
Python is a 'good enough' lisp. MIT switched, and Norvig has said as much.
No, the astonishing thing is that Python survived the 2->3 transition, and came out stronger on the other end. Language cleanups, new 'syntactic sugar' (e.g. @ as the decorator syntax), and what you see is Python is trying to actively steal all the successful programming paradigms under one unified syntax.
Is python perfect? Hardly. But it's beginner-friendly and expert-optimized. AND, unlike C++ (at least for me), you can get ALL of Python into your head at the same time. (Libraries, ok, but true in any language). In this specific sense, it is exactly like C (you can keep it all in your head, even the edge cases).
There are newer languages gunning for a piece of Python's mindshare (Zig, Nim). But because Python is a moving target: getting better and better, the others will need to provide a spectacular use-case advantage --- and I just don't see that happening.
I don't think there was any toxicity in the Ruby community but it was made up of working programmers where as the big leading voices in the python community was teaching assistants and students so it might have been more tailored to newbies.
I don't recall there being much real industrial use of python prior to Ruby emerging even if python is technically older so i think the real answer lies in why the educational sector decided that teaching python was easier and significant whitespace plays a huge part here.
Yeah that's my recollection too. About 2011ish there weren't a lot of jobs in python yet. Perhaps in SV, but not out in the real world. Several startups were doing it, including Youtube and google at the time.
But in the F500 world, python wasn't used at all. I started using it in 2008/9-ish.
Not GP, but the Python 2 vs 3 holy wars were also something that kept me from adopting Python as a scripting language a couple of years.
I mean, I love python, but that sucked!
Yes it would have been more work for the devs, but the amount of work it meant for the users were worse.
In fact they pretty much just threw away anything before python 3.6 anyway now. Many things introduced in the 3.x series before 3.6 just don't work anymore (asyncio syntax being the notable one).
That is literally what 2.7 was, as well as reimplementing some features in later p3 (up to 3.4).
The core team definitely had the wrong transition model at the start, and it took some time for the community to convince them then decide on which items were the most important, but let’s not act like they did not get it in the end.
> In fact they pretty much just threw away anything before python 3.6 anyway now. Many things introduced in the 3.x series before 3.6 just don't work anymore (asyncio syntax being the notable one).
What?
Better supporting cross-version transition codebases.
The core team initially saw the transition as “run 2to3, fix what’s left, publish updates, P2 is gone”, but aside from 2to3 being quite limited such transition is quite hard for dependencies, as it means they leave all older dependents behind entirely (dependents which might be the primary user for e.g. company-sponsored projects), or they have to keep two different codebases in sync (which is hard), plus the limitations of pypi in terms of versions segregation.
What ended up happening instead was libraries would update to 2.7 then to cross-version codebases, this way their downstream could migrate at their leisure, a few years down the line people started dropping P2.
> Are there any languages with major breaking changes that have done the upgrade smoothly?
Some but usually statically typed languages e.g. elm’s upgrade tool worked pretty well as long as you didn’t have native modules and all your dependencies had been ported. I think the swift migrator ended up working pretty well after a while (Swift broke compatibility a lot “initially”) though I’ve less experience with that.
An alternative, again for statically typed languages more than dynamically typed ones, is to allow majorly different versions of the language to cohabit e.g. editions in Rust (Rust shares the stdlib between all editions but technically you could version the stdlib too).
Not workable for Python, not just because it doesn’t really have the tooling (it has some with the __future__ imports but nowhere near enough) but also because it changed runtime data model components specifically the entire string data model, which is not a small matter (and was by far the most difficult part of the transition, and why they piled on smaller breakages while at it really).
Of course I already knew Python, and so did the rest of my team so we had been doing tools in Python (the guy wasn't on my team), but until he pushed ruby into places where python would have been better (import a Python library rather than shell to out to a program) I was willing to accept it was probably fine '
I mean, if you read almost any Elixir article that has hit the front page of HN, there are always comments from Pythonistas saying, "Why bother when there's Python?" Similar attitude. Obviously it's not everyone, but it's not everyone in the Ruby community either.
Not that I care much these days since I prefer writing in Elixir.
The only ruby person i've met was insistent that ruby was the one true way
That sucks. I've been doing Ruby full-time since 2014 at 4 companies and I've never seen that sentiment. My experiences have been really positive.I was arguing for the F500 company I was working on to explore using Jython to write unit tests for Java code.
Why not have a scripting language to write unit tests for Java code?
I see this with Rust trying to extend python in interesting ways. I don't see this with Java trying to extend C/C++ or Python.
“Matz is nice and so we are nice” https://en.wiktionary.org/wiki/MINASWAN :)
The Rails community is another story, unfortunately.
Honestly, your critiques seem more like opinions. The comments are pretty spot on that these are not issues. Your perspective on the default data types is off though. This is not an attack. I simply disagree with you descriptions and opinions.
These people learned only Python, don't know any other programming language, and now evangelize it to everyone, making excuses for its obvious faults and problems. That's the essence of this community.
We detached this subthread from https://news.ycombinator.com/item?id=37315605.
Even Java puts it to shame and that is sad
The Python documentation seems to be suffering from some sort of weird snobbery. Very wordy as another comment mentioned. Examples are frequently lacking or inadequate. They seem like they're trying to compete with MSDN in "professionalism" although these days even the MSDN examples are better. There is an entire ecosystem of python tutorial websites around the web that would not exist if the documentation was as helpful as that of PHP.
I just wish Python applied this approach to package management. It is needlessly complicated.
I really fail to see what the newer tools actually bring to the table. From my experience they solve no actual problems and just introduce more bugs and weird behavior.
Python has been really winning for some time, so it's natural that its ideological discipline has grown ragged. The crop of kids who value options above consistency don't have the scars of the Perl age to inform their prejudices.
But Python is -dramatically- better focused, as a community, on finding a Pythonic way to proceed, and then advocating it, than previous cultures.