58 comments

[ 3.5 ms ] story [ 124 ms ] thread
That's 4 months old and the discussion is locked on it.
From the official FAQs[0]:

If a story has had significant attention in the last year or so, we kill reposts as duplicates. If not, a small number of reposts is ok.

252 points/261 comments probably qualifies as "significant attention".

[0] https://news.ycombinator.com/newsfaq.html

Python was my first programming language love. I had a few false starts: Logo when I was very young, which I found too useless. Perl, which made no sense to me as a middle schooler. Actionscript came close, I was eventually able to create a Flash game in high school, but the API was still too arcane for me to actually like it.

In college, Processing.js was what I used in the Intro to Programming class, which was fun, but like Logo, not powerful enough. Java (why do I have to type so much?) and C (why do I have to worry about memory allocation?) for the intermediate courses. But I never really enjoyed a language until one of my upper division classes had us work in Python.

Finally, a reasonable language. Easy to pick up, but very powerful once mastered. Easy to read, quick and concise to write, thanks to the syntax and interpreter. A massive amount of open sources packages to choose from, for nearly any programming task you can think of. A sane blend of functional, object-oriented, and procedural features.

Python was the language that made me actually enjoy programming. Thanks GVR!

> why do I have to type so much?

As someone who came to it from Ruby, that is often my question about Python :)

Same from Groovy!

I can understand why a lot of people start with Python. I can't work out why they stick with it once they become more advanced and understand its limitations though.

I feel it really depends on one's background. I'm doing backend with Python now but came from academia where Matlab used to be the tool/language of choice. However, more and more academics got sick of working in that walled garden and paying oodles of money to use it and Python was a fantastic alternative to that.

I believe that if you're walking the line between software-development and data-science Python does an excellent job of bridging the two.

About 8 years ago, I moved on from Apache Groovy to Clojure which is far less verbose. Well placed macros in a testing script reduces a lot of clutter. Clojure has a longer ramp-up time than Groovy though, but once mastered is far more effective. I stayed with Clojure until I moved off the JVM about 5 years ago.
I am curious where you ended up? I have not found any substitute for the JVM for a flexible, rapid development yet high performance, stable and mature environment with a large base of library and deployment option support.
I'm a Python developer (web back) who occasionally does some fixes on legacy RoR project and I always ask myself why does Ruby needs so much sugar. Also it does not look very consistent to me, but it's probably because I get to practice only once in a couple of months.

After Java, CPP and Node, Python looks to me as the greatest of all. Syntax is just comes to you and usually does not produce problems. And Python even right now has so many areas of application, and does it without much compromises, that I wonder why would I want to change anything.

I programmed in python for years, am starting to code in javascript/node and am really liking it. Typing in python is weird, i much prefer flow/typescript. Async in python has a history of being weird, from twisted, to yield from, and finally to async/await (which still has some issues, but is much better). I thought javascripts "callback hell" actually made sense, promises made it easier, and now async/await which works great. Pip has a long way to go to catch up to npm/yarn (i cant believe im saying that). Virtualenvs are weird, even though node_modules can be bloated i think its a lot more intuitive.

Anyway, long winded answer that i think i prefer node after a lifetime of python

pipenv replaces pip and virtualenv, and is actually decent.
Pipenv looks good on paper, but it is a total trap. Pipenv breaks differently on every single release. The user experience is absolutely hideous.

I am currently in my third hour of getting a pipenv+pyenv python project running. I started the project this past summer, and have reinstalled it three times. Each time I have spent 3-6 hours getting pipenv working, and each time the errors/problems/workarounds are completely different!!!!!!

All I know is it works well on our projects.

I'm not the one doing any dirty work though...

> Typing in python is weird, i much prefer flow/typescript.

I find the exprience working with TypeScript and Python/Mypy very similiar. (in VSCode)

> Async in python has a history of being weird, from twisted, to yield from, and finally to async/await (which still has some issues, but is much better). I thought javascripts "callback hell" actually made sense, promises made it easier, and now async/await which works great.

Both ended up with async/await. I find async programming is similar annoying in both Python/JS.

> Pip has a long way to go to catch up to npm/yarn

I don't see a big difference working with pipenv/poetry compared to npm. Once your project structure is configured it boils down to `pipenv install`/`poetry add`/`npm install`.

> Virtualenvs are weird, even though node_modules can be bloated i think its a lot more intuitive.

Again, once configured I don't see a big difference (from a user's perspective). One system puts your packages into `npm-packages` the other puts them into `some-venv-dir`.

I think npm works better out of the box, but you can configure your python dev enviornment very similar, if you want, without much effort.

To me working in either TS/Python+Mypy feels pretty much the same.

I’ve always loved django, and graphene isn’t half bad for GraphQl in python, but it’s getting harder and harder to deny how useful JavaScript is becoming compared to python.

An Apollo/yoga graphql setup with node and prismsa is just really, really productive.

There is also the advantage of sharing environment between front and backend, I mean, there are just so many hours, it’s hard to keep up with two major languages and their communities (two and a half if you’re using typescript).

Ruby has its problems. To me, mostly all the Magic. Since I'm a programmer and not a wizard, I struggle with magic... I mostly mean that almost anything can be redefined by some crazy Gem someone added to the project in some file far, far away.

I truly love that in Python I can look at my import statements and know what code is happening in a file!

But, man, it is tedious to so often have to use 5 clumsy lines for what Ruby could have said better in 2...

Sure, Ruby is not "consistent" in that there are several ways to do things. And with more tools at your disposal, you can get many things done easier!

Second that, I could recite the Pickaxe book from memory by the time I gave Python a serious try. And I could never really get over loosing my Ruby toys or having to memorize arbitrary quirks like variable scoping, method overriding and more. And I think I gave it a fair chance, went to conferences and even got code published in one of the bibles. Ruby feels like a smaller language to me, it doesn't take as much space in my brain. And since my brain isn't exactly aging with dignity, I'm designing an even simpler language [0] for days to come.

[0] https://gitlab.com/sifoo/snigl

It is funny to consider the path in languages. My first had to have been some form of basic. Couldn't tell you which dialect nowadays, been too long. That said, I probably didn't do "real" programming til BBS days. Don't know what language those were. Toyed with SQL in my final year of high school. Tried making a D&D character sheet program. College was a hodgepodge of vhdl, c, java, matlab, and lots of pseudocode.

It wasn't until many years later that I touched lisp. I had seen it mocked before, but never used it. That said, I have since found that same sort of joy in programming that you seem to be describing. Only, instead of a "powerful once mastered" feel, I get more and more of "I remember finally grokking this idea in other languages, it was really this easy!?"

Python, in all of this, has fallen by the wayside in a way that I'm just annoyed by all of its claims. Notebooks don't make it any easier. Much of their charm is in areas that I feel tools I was able to use in college easily touched. Matlab is, in particular, an amazing program. Once you get used to it.

I'll give python the credit of being where everyone is today. There is a lot to be said for that. The language doesn't spark any joy for me, though. :(

>Python, in all of this, has fallen by the wayside in a way that I'm just annoyed by all of its claims. Notebooks don't make it any easier.

Could you clarify what you mean here?

Apologies on the slow response.

Python is claiming to be easier to read and faster to develop. Often (always?), without data. Notebooks are pushing something close to a live coding session, but having to recreate so much to get there.

And if you had ever used other environments, it is frustrating to see people lauding and making progress and tons of press, all while pushing bad practices.

That is, it isn't that nobody could or had done these things. If you care about productionizing, you just need a more formalized environment. You needa more pluggable setup. Just hitting "play all" again on a notebook is good, but is a very low bar. Or puts more effort on parts that don't matter. Often both.

So, I meant all of that at a personal level. I feel like the entire industry is trying to sell me something on faith. Or appeals to the impressive products of people that likely could have used any tool. It hits many of my "don't trust me" vibes.

Python was not the first programming language I wrote a program in, but it was the first one I actually ran.

When I was a kid I wanted to make games, I picked up a book on C from the library. I wrote a simple interactive fiction type game but with never managed to compile it.

When I tried out python a couple of years later I was blown away. I could actually write and run programs. I wrote a mandelbrot set generator and I was hooked. This is what programming is supposed to be like, I thought to myself.

A 5 year old can do bit of Python programming :). Start terminal, type Python and then type 2 + 3. Watch them getting kick out of typing huge numbers and Python spitting out the answers.
Same with Haskell or ML family languages.
Ahhhh, but then they will ask how to print things and you'll have to explain monads :)
I thought we were talking about a REPL instance. Have you already explained how to use a command line and what files are and how to run them? stdout?
You need none of that in a jupyter notebook.
Jupyter supports Haskell too though. As well as OCaml and Scheme...
Just tell them they are like burritos. ;)
Zygohistomorphic prepromorphisms[0] are a common topic of discourse among five year olds, for sure...

But more seriously, I strongly disagree about Haskell being anything like Python is for kids.

The level of abstract reasoning that Haskell requires for more than just adding two numbers is not easy or intuitive for kids. Following step-by-step instructions is intuitive. Writing Python line-by-line is easy to understand by analogy to a list of instructions. Eventually they can start using functions when they're comfortable, but you're very unlikely to succeed in teaching a five year old about typeclasses, monads, functional purity, effect systems, or anything like that. The thing with Haskell is that you have have to know almost all of that to do anything useful from day one. Even something as simple as drawing lines on the screen.[1]

Don't be ridiculous by suggesting Haskell is just the same to five year olds as Python.

[0]: https://wiki.haskell.org/Zygohistomorphic_prepromorphisms

[1]: https://docs.python.org/3.7/library/turtle.html

Yes, I know the jokes about zygohistomorphic prepromorphisms. How about you try explaining Python decorators and object-oriented design to a five year old?

> The thing with Haskell is that you have have to know almost all of that to do anything useful from day one.

Okay, then how is adding two numbers together useful? If that's Python programming then the equivalent counts as Haskell programming. You are setting a double standard for what you expect a 5 year old to be doing.

Even then, tell me which of these is simpler and more clear:

  def double(x): return x + x
  double x = x + x
or, perhaps

  let f x = x + x
The point I'm making is that with regards to syntactic complexity, Haskell and Python are similar, (in fact Haskell is actually _far_ simpler) and with regards to conceptual/semantic complexity, you have to be fair in comparing them together. You do not need to understand typeclasses, monads, or effect systems to do basic Haskell programming in GHCi.
My suggestion is that they won't write functions, not for quite awhile. Why would they ever need to understand decorators or object oriented design to start writing code!? They can write actual code though, not just addition in some REPL. In Haskell, you do need to understand a crazy number of things to do anything.

That "actual code" I mentioned can involve drawing on the screen, which as I pointed out in painstaking detail, is not going to be explainable to a five year old with Haskell code. That kind of visual feedback is incredibly important to concrete learners, which everyone is at that age.

Haskell and Python are not similar with regards to "conceptual/semantic complexity." At all.

I have used Haskell in the past. I understand it. Someone who hasn't reached Piaget's "formal operational" stage is not going to understand it. Piaget's theory isn't perfect, but it is normally true that people start out at a very concrete level.

As I said, don't be ridiculous.

Here is some super complicated Python code that kids can learn a lot from:

    from turtle import *
    
    color('blue')
    forward(200)
    left(90)
    forward(200)
    left(90)
    forward(200)
    left(90)
    forward(200)
    left(90)
    
    done()
Eventually, they'll move on to using for loops! Or even asking the user a question and drawing something based on that. You literally have to understand (at a basic level) monads and effect systems to start implementing a question-response system in Haskell.

Please, show me what my above code looks like in Haskell, since it's so comparable in complexity.

I don't think you have an appreciation for what goes into learning programming. You've probably been doing it for far too long at this point, without thinking back to the early days.

Why are you so defensive about Haskell in the first place?

https://cdsmith.wordpress.com/2011/08/16/haskell-for-kids-we...

Books like The Haskell School of Expression have been teaching functional programming using simple graphics in Haskell for a long time. Need I remind you that the entire concept of a Turtle comes from Logo, which is Lisp minus parentheses?

What a terrible book that is... The Haskell School of Expression was the text for one of my early CS courses, and was a significant contributor to my bailing on a major in CS and going to something more sensical. Since then I've picked up a handful of other Haskell books, and without exception they have been far better suited to actually teaching programming.
I never said Lisp nor Logo was a bad choice, now did I? Lisp is incredibly simple, even if it makes some things obtuse for beginners. I would rather have a strong type system like Haskell's for working on a large application, but Lisp is way easier to get started with. The parentheses are a huge stumbling point, though, which is where Logo comes in.

For the record, those kids do not look like 5 year olds. Once someone is old enough to do abstract reasoning, I think Haskell might be a workable choice, if carefully taught. More often than not, it's more likely to drive them away than something simpler. That article appears to be using some web interface which was designed to hide all of the monads... I think that's a splendid way to get started. The students aren't writing their "main" function. Unfortunately, the website linked from that website is down, so it's hard for me to verify.

You haven't been listening to anything I have said, so I'm going to stop. I wish you would reflect on software education, because however well-intentioned, starting with Haskell is likely to drive many more people away than it would help to show what they can accomplish and inspire them.

So we basically agree. You seem to have drawn from my comment that I think Haskell is some ideal language for teaching programming to babies. No. I merely said that basic math is similarly simple. I mentioned ML as well which you completely ignored, and in later comments I talked about Lisp and Logo. I was just trying to broaden the discussion to functional languages which are often passed over as teaching tools these days because they are frequently viewed as too difficult to understand or useless, when the actual genesis of CS pedagogy in children is with Logo and Lisp. Apologies if my comment was unclear.
I'm a Haskell programmer. I agree that Haskell is as expressive and fosters an ease of readability like Python. But to say that you can do basic programming without understanding type classes, is taking it a bit too far.

In fact, as far as teaching 5 year olds is concerned, I'd go with Lisp rather than Python.

Sure, Lisp, ML, whatever. The point is not that Haskell is the absolute best language for beginners, but that Python is not lightyears ahead of it as regards clarity and readability. I think you _can_ do basic programming without typeclasses, and even then, simple typeclasses are not hard to explain. In fact, I think Num might be easier to explain to a 5 year old than the distinction between Int and Float is.
I'm getting downvoted on this comment for basically saying that GHCi or utop will let you type in 2 + 3 and see 5 as a result too. The point I was trying to make was that if that counts as programming then it is not specific to Python. Ruby has it as well, to use a less scary example.
I don't disagree that 2+3=5 is inadequate, but to be fair you do hit a complexity wall pretty fast. If i've understood correctly, Haskell has two main datatypes for collections, lists and tuples. Using [1], if I was a 5 year old (or a 50 year old) to find the length of a list or tuple i would do this:

λ length [1,2]

2

λ length [1,2,3]

3

No problems here. Now tuples:

λ length (1,2)

1

λ length (1,2,3)

No instance for (Foldable ((,,) t0 t1)) arising from a use of ‘length’ In the expression: length (1, 2, 3) No instance for (Num t0) arising from the literal ‘1’ The type variable ‘t0’ is ambiguous Note: there are several potential instances: instance RealFloat a => Num (Complex a) -- Defined in ‘Data.Complex’ instance HasResolution a => Num (Data.Fixed.Fixed a) -- Defined in ‘Data.Fixed’ instance forall (k :: BOX) (f :: k -> *) (a :: k). Num (f a) => Num (Alt f a) -- Defined in ‘Data.Monoid’ ...plus 7 others In the expression: 1 In the first argument of ‘length’, namely ‘(1, 2, 3)’ In the expression: length (1, 2, 3) No instance for (Num t1) arising from the literal ‘2’ The type variable ‘t1’ is ambiguous Note: there are several potential instances: instance RealFloat a => Num (Complex a) -- Defined in ‘Data.Complex’ instance HasResolution a => Num (Data.Fixed.Fixed

A quick googling does not tell me how to find the length of a tuple. The closest thing to an answer is, 'you probably don't actually want to do that'.

[1] https://www.tryhaskell.org/

Tuples have fixed size and are typically short and are not really collection types. They are a compound scalar that is meant to associate meaning with each position. Tuples can contain different types because of this, while collections are typically homogenous. Tuples do not also really have the concept of “empty” indices, in the way that fixed-size arrays do.
That's basically the 'you probably don't actually want to do that' answer that i mentioned at the end of my comment. I don't think its a good answer in the context we are discussing:

1. If you gave this response to the hypothetical five year old, you will simply make them cry, and then they will quit programming.

2. If you give this response to the hypothetical fifty year old, they will feel you're hemming and hawing to cover a weakness in the language rather than giving a more direct and honest answer.

In regards to (2), I'm not literally a 50 year old learning Haskell, but I am an adult teaching himself how to program for the first time, starting with Standard ML. Perhaps if you have a few minutes you'd be willing to let me elaborate on my complaint and check my understanding?

The main issue i'm imagining is modeling homogeneous data vs heterogeneous data. With tuples, the types of data are encoded in the tuple type, and are known at compile time. In SML its a product, so a tuple of length 2 is a different type then one of length 3. Presumably this is what you meant by 'not really collection types'?

Tuples of different lengths having different types is, if i'm understanding things correctly, the key point for this discussion. If i want to write a mythic 'tuple length' function in SML, it has to be generic enough to work on something of type a->int, and a* b->int, and a* b* c->int, etc... And so it has to make sense for any 'a->int (where 'a is a variable), which is to say it can't know anything about the structure of tuples! Is this reasoning correct?

Assuming it is, you can see why I called those answers 'hemming and hawing'. This is clearly not something put in the language based on some prior logic about indices or collections or fixed sizes...nobody wants to not be able to write functions from arbitrary tuples; it appeared as a design trade off in order to access type information at compile time. It also is not specific to the length function.

A second strategy to model heterogeneous data is to use a homogeneous collection like a list but then use a sum type to introduce heterogenity. This makes a different trade off: the types are the same for different sizes so we can write functions easily (including length!) but the types are the same so we've lost access to compile time information, and the class checks from the sum are done at run time.

Thanks for taking the time to read this far and correct my misconceptions!

It’s just the definition of a tuple. Having fixed length and tuples of different lengths being different types is important because it means you can pattern match on them and from that you also get things like destructuring and so on and so forth that you do not have with lists. You can call it a limitation but it’s more just about the design philosophy of a tuple. You can get the nth element by pattern matching, which you cannot do with growable data structures. You probably do not want a function that operates on all tuples in the first place, because making that possible massively reduces their utility for places where they are useful in the first place. Basically, use a different/real collection type if you need to do this. Tuples offer specific features that other types do not have and are constrained in their utility because of this. Records and arrays are often a better choice.
Hard to compete with the likes of logo and the modern scratch terminals. Sure, having a kid see addition is fun. But, they also think my old calculator is fun for stuff like that. Being able to build things in minecraft using a programming like environment? Bloody awesome.
Unlike jolux's comment, I can agree with yours entirely. The tighter the feedback loop between code and graphical response, the more enticing it is to new learners. Scratch takes away the pain of trying to type picky syntax. It's a great starting point.
More than just the feedback loop between code and response. The feedback loop between what you have to do, and what you want to happen.

Rather, I'd reword it. Just getting faster feedback from coding to some response is not enough. It has to be to the desired responses. (So, for example, it doesn't help to get faster feedback to syntax highlighting.)

(comment deleted)
I found this article to be profoundly weird in a lot of ways. It's not quite suffering from the "igon value" problem, but gosh does it come close. It's hard to measure programming language popularity, and most estimates I've seen have Python neck and neck with JavaScript with regards to popularity. Plenty of other languages have simple syntax and are easy to read, the only thing I would say Python has that is clearly superior is availability of packages and community support, (and even then JS has got to be close there) which are undoubtedly huge, but I think it's fallacious to assume that those reflect intrinsic technical worth.
>Plenty of other languages have simple syntax and are easy to read

As easy as Python? That's a very high bar. We all agree (I hope) that JavaScript requires linters (plural) to write well. Rust/Scala/Haskell have unpleasant learning curves. Java is verbose and clumsy. Basic and Pascal have fallen into disuse. Go may be simple, but it's syntax is more symbolic and less English-like than Python. Don't get me started on Perl and the lisps. C/C++/PHP have more footguns than features.

I'm not a Python die-hard, but it's obvious that it's superior when it comes to ease-of-use and learning curve. It's very similar to how people write pseudocode.

I will argue that learning curves are similar with Ruby, SmallTalk, ML, and Scheme to Python. Logo is the original teaching language, and I think is similarly easy. It's my belief that people exaggerate the learning curve of Haskell, but whatever, I'll grant you that.

If your criteria for readability is "English-like" I think you're missing a lot of what makes Python so readable in the first place. It is not very English-like at all. Compare to say COBOL, which actually had English-like readability as a design goal and was by all accounts an unmitigated disaster. AppleScript has a similar reputation for being a "read-only" language because of how difficult it is to pick up from reading it. What makes Python readable is having a small number of concise syntax constructs that compose into complex programs, the same things that make functional code readable. The presence of words vs operators is probably important, and Haskell tends towards the latter, but the ML family doesn't, and Lisps are plenty readable if you keep them simple. There's a reason that SICP and HTDP use Scheme, the latter using a gradually larger subset to make it less intimidating.

As a part of my college curriculum most students are required to take a programming course; I got put into the Java course. Although I was good at it, I hated every minute of it because it felt like I was fighting the computer to make things work.

I played around with PHP in order to make hacks on WordPress themes, which again I hated due to system-fighting.

I learned base R (pre RStudio/tidyverse) for stats classes, which I hated even more than the previous two since everything felt combersome.

Then just for fun I installed Linux on my laptop and experimented scraping APIs with Python with only a few lines of code and I got hooked.

Nowadays I use primarily Python for both work and personal projects. If I had started with learning Python, I would have had a much different career path!

Java has some advantages over python in a teaching environment.

Writing a basic hello world function you’ll learn about types, return values, references, imports and access modifiers, all in three lines of code.

Java is also excellent for building stuff like various linked lists to see how the lists and arrays we all take for granted actually work behind the scenes.

The confines of Java’s strictness is also a really great sandbox in which to teach best practices without students ever getting in danger, because java will tell them every time they do.

I know a lot of teachers really struggle to do it well, but going through public void X, word for word can be extremely useful in teaching. For one, it’s very easy to spot who knows what is happening and who is just copying stuff to make it work.

I think python is quite terrible for teaching beginners, but it’s certainly fun to write. These days, I think JS and Node is more fun than python but that’s mostly because it’s where a lot of the fun is happening, I certainly could do without all the {s and ;s.

I disagree. Those three lines of code are three lines of utter black magic to a beginner. Things are only useful insofar as they solve a problem, and the beginner hasn't yet encountered the problem solved by types yet, so there's no reason to teach them.
Well, after the first programming lesson, they are no longer magic. In python, they are never demystified.
Right. Let's learn 50% of all the mechanical aspects of programming in one lesson. Those just serve to get in the way of initial learning, general program flow and logic.
Those few topics aren’t close to being 50% of the mechanical aspects of programming. What are you even on about?

Furthermore they are all easily explainable concepts that any CS student will be able to grasp once they reach their first programming language course.

I’d say most of the concepts are easy for non-CS students as well. Access modifiers, especially public and private aren’t hard concepts, are they? Yet they are insanely important to your basic understanding of what a function does. Private is like singing in the shower, you’re doing it for you. Public is like signing at a concert hall, there you’re signing for the audience.

Return values are values functions return, your can think of them as the result a calculator gives your when you ask it to add 2 and 2, here the return value is 4.

Types are typically the first thing you explain anyway, including when you teach python.

Maybe you could get people writing complicated functions faster in python, but why would you want to? The purpose of teaching programming isn’t to have people writing code as fast as possible, it’s to teach them to understand what the hell it is they are writing, so they’ll know why they do it.