Hacker News new | past | comments | ask | show | jobs | submit login
Why People Should Learn Python (iluxonchik.github.io)
345 points by LaSombra on Aug 24, 2016 | hide | past | favorite | 319 comments



Is it just my feeling or are there languages which are preferred on HN?

Indicators for languages which are liked by the HN community:

- Positive stories get many upvotes and are instantly at the top of HN

- Most comments are positive

- Frequent coverage on HN about the language

Indicators for languages which are not liked by the HN community:

- Rants get many upvotes and are instantly at the top of HN

- Most comments are negative about the language

- Rare coverage on HN

Applying those indicators, following languages should have these like-levels (on a range from 1 to 5):

  Python  *****
  Go      ****
  Node.js *
  C#/.NET ***
  Java    ***
  RoR     **
  Ruby    ***
  Elixir  ***
  Haskell ****
  Closure ***
  C       ****
  Rust    *****
  C++     ***
  PHP     *
  Swift   ****
  
This is just my feeling, happy to hear your perception. And this does not reflect my opinion about those languages in any way.


At a glance, it looks like all languages are reasonably well loved except PHP and Node.js (shouldn't this just be Javascript? Does having a different standard lib make it a different language?)

I think that's due to people having flash backs to terribly written code in both languages.

For example, PHP apps pre-2005 rarely if ever used frontend controllers, preferring instead to twine in configuration and helper functions into isolated pages that were directly served by Apache. This meant that there was no single obvious place to put things like caching.

Additionally, once upon a time, PHP didn't really have well developed ORMS, so everyone just wrote queries and hopefully parameterised queries---but not always. So if you had a hobby project that took off, then within 3 years it'd be a roiling ball of mud where it's difficult to do basic things like tracing which calls happen per page.

PHP came to prominence early in the web, and it was easy to use so everyone had a hobby project that took off, or had to work within something like that. Hence the hate.

To compare it to Javascript, I think the disdain for both languages is due to their initial nature---they were both written over an short period of time, and evolved in spurts rather than being carefully designed from day one or designed to overcome the shortcomings of another language.

The quality of the above really shows up in the inconsistency of the standard libraries, and the fact that certain semantics were inconsistent or danger zones in practice but couldn't be changed.

---

I do remember though when everyone hated C, and loved C++, then went back to loving C... so maybe programmers are just fickle and none of what I said makes sense. :)


With PHP, I'll agree, though with JS I think it's the reverse. At least my personal dislike for the language and the ecosystem grows with every new hot framework, build system, or other weird "must-have" link for the toolchain that Node people seem to create almost daily.


The JS community is considerably larger than all other programming communities, and better at promoting (and documenting) its tools/libraries/frameworks (a lot of these tools come with beautiful landing pages, docs and demos).

That shouldn't be seen as a mark against the technology. Nobody is forcing you to switch tools.


> That shouldn't be seen as a mark against the technology. Nobody is forcing you to switch tools.

Except when they do because they're the front end team. :P


Well you should really have that out with them! If you feel they're needlessly switching and putting your project at risk, have them justify it.

(Or just have a rule that as a team you try e.g. '1 new thing' per project).

Again this shouldn't be a reason to hate on the JS community.


I have to agree.

As a hobbyist Node developer (day job is not in Node), I find it hard to talk with other Node developers as there is some build-tool or even full framework that sits on top of Express that I "should" be using but I'm not. But maybe it's just me.


> Node.js (shouldn't this just be Javascript? Does having a different standard lib make it a different language?)

I think the dislike comes from the idea that JavaScript-development can be or at least was very messy and that "the JS-people" now try to carry that over to the server-side.

npm also has many issues and node as a server-side VM wasn't very dev-ops friendly in the beginning, if I'm not mistaken.

Note: This doesn't mean I don't like JS or node, I use them daily, though I have never used a production node-server. I'd rather run my JS on the JVM.


just to chime in on this, modern PHP is nothing like what people remember from the pre ROR days, i still use it to this day and the major frameworks and libs are really well written to the point i feel some are even over engineered and almost looking like Java (just take a look at the latest Guzzle PHP Library)


As my PHP fluent colleague said to me - don't bother learning PHP or you will end up having to fix (our) Wordpress sites and thats a nightmare. We have a Python application, and while its not written well, the PHP sites we have seem to be a fair bit worse even the ones not done in Wordpress.


Wordpress is horrible. Never going to touch that again (Senior PHP Dev myself) or anything else like it (Magento, Drupal,...).

And yes there is a lot of horrible PHP code out there, writting by bad developers. I guess newer or not as accessible languages don't have as many bad devs as PHP/JS.

But if you have good devs, I prefer a good PHP codebase to any other language that I have come across (I tried a lot of them).


Around 2001 I felt jaded with the industry and determined to do whatever was expedient to earn money. That meant using PHP, because that was purportedly the place to be at the time.

I have never felt so uninspired by a language. My overwhelming feeling from the get-go was that it was a collection of libraries, which would be fine -- but why create a new language?

PHP has the rare distinction among languages of not containing any novel features or ideas. Not only that, but it borrows liberally from several other languages, resulting in an overabundance of syntax. Instead of a tool for attacking problems, it's a reheated leftover. There is not suggestion of a better or worse way to accomplish some goal.

Finally, the original premise of PHP, interspersed functional code and HTML, is high on my list of really bad ideas. Code written in this style is doubly-challenged in terms of reuse and maintainability. Again, there is again no semblance of better or worse with this approach. If you had Richard Stallman and Linus Torvalds produce the same website with PHP, there would be very little in common between their approaches.

Given the success of Facebook et al, I presume that the interspersed code/html thing has been superseded, and further that the egregious security issues in PHP have been fixed. But the picture in my mind's eye is something that lumbers along despite its thorough mediocrity. I will allow that making PHP adequately consistent and secure are impressive feats.

Sincere question: how am I wrong here?

====== edit ====== Drop extra 'the'


Since when did something need to have novel features or ideas in order to be productive?

I'll counter that one of the main reasons PHP became such a used language (other than ease of deploy) is exactly the reasons you dislike it. There are multiple ways to do things - that coincide with the ways you do things in many other languages (which it steals from).

You dont have to learn anything radically new to use it, and that makes it very easy to do things quickly.


"Since when did something need to have novel features or ideas in order to be productive?"

It doesn't. But if your language ideas are admittedly no better than the next guy's, what's the point?


It's easy, fast (both Development speed and Page Views), and can deploy anywhere with a few clicks? It has no novel concepts that require learning something new. It has a plethora of existing code, documentation, frameworks, and StackOverflow answers to solve almost any problem (albeit, not always correctly).

Its the lowest barrier to entry web language - and honestly, I'm ok with people writing shit PHP. It gets good Ideas out there quickly - allowing the business to grow without a focus on the Development. This creates opportunities for sharp developers to come in and work on proven ideas.


It can be a combination of different things that exist somewhere but not in this combination.

For me PHP is like Java but with sane nullability. It's like python but it actually has interfaces so that I can do proper OOP.


Currently, with version 7.0, its implementation is faster than most other scripting languages.

That's one big important point.


2001 was 15 years ago. PHP looks completely different now. It looks very much like Java with -> instead of dots and a few differences.

Nobody sanes mixes HTML and PHP code anymore these days. Most people are using Twig for templating or at least something similar. Everything (decent) is object oriented these days.

So your views were correct 15 years ago, but have a look with fresh eyes and you will see something completely different.


Not disagreeing with you, the "javafication" of PHP has been going on for a while now (for better or for worse), but pluck your average person using PHP out from a crowd and they are still writing code like it's 2001.


If you pick an average person, then yes maybe. But that's because it's so widely used by non-developers.

But if you narrow that down to actual developers who have a job working on a product, not someone hacking a wordpress template, then it will look much different.

Not saying the average PHP developer is great at OOP, but at least things are moving into that direction. And the code quality has come very far since 2001, just look at at current open source libraries (see packagist.org) and compare them to old PHP code.


> I have never felt so uninspired by a language.

I agree with this sentiment very strongly. I understand that there's a lot of hate, flamebait, etc etc about the language, with which from my own experience I agree with or disagree with in fairly equal parts. At this stage, I have written more large web projects in PHP than any other language (for varying reasons). I don't proselytize on why it is (or is not) a good language. But for me, personally, a huge chunk of whether I'm happy or not comes from whether I feel inspired while I'm working. Quite separate from the excitement of solving problems: while working with Rust or Python, I get excited, and am generally happy (even when fighting with Rust's compiler); while working with PHP, I tend to feel vaguely annoyed. Take from that what you will.

I'm of the opinion that the best tool for the job is the one you know how to use, and in the real world of deadlines and opportunity cost, if you get a great PHP dev to write your application in Python it's going to be far more expensive and far worse than if it had been written in PHP. But it's also going to be far less fun to both write and maintain. I think you have to make your language decision depending on your priorities.

> the egregious security issues in PHP have been fixed

This I strongly disagree with. And I don't think it's possible. It's not that the existence of the language includes vulnerabilities, it just makes it extremely difficult to write applications securely. I actually teach an upper-division university class on Network and Application Security, I am writing my PhD dissertation on the topic. I have worked on the internal security team of a very large company, and I have worked as a penetration tester / security auditor. I am very familiar with the vulnerabilities that plague web applications. And I still occasionally find the odd XSS vulnerability, timing concurrency attack, etc. in PHP code that I myself have written. And most PHP applications are not written by people with my background.


"while working with PHP, I tend to feel vaguely annoyed"

Exactly! I was never satisfied with my PHP code, as there does not seem to be a better and worse answer in many cases.

For the record I did not mean to assert that PHP has become secure, I meant that I presumed it had. Some years ago it was a laughingstock on Bugtraq.

Thanks for the feedback!


Have you tried working with Laravel 5.2+ ? Instead of doing tons of for-loops, etc..

You can easily create a collection from data and process it. For example using the DB class to get data returns an array of Std objects.

For a legacy app I'm working w/ --it needs to be an array of arrays... I could for loop, and then add each to a new array.. or I can simply do:

$data = DB::table('something')->where('something')->get();

return collect($data)->map(function($x) { return (array) $x });

There's a talk at lara-con on using collections to replace just about all loops, and it's pretty insightful and makes code so much more readable and enjoyable.

PHP by itself can be ugly -- but the Laravel community has created something beautiful from what used to be akin to horse shit.


Laravel is still horse shit that does not follow good OOP practices.

Static calls and active record are not good OOP. Neither are Std objects.

Have a look at doctrine if you need an ORM. Otherwise read up on DDD and SOLID.


Ten points for the reheated leftover bit.


I'm a php dev, and as much as I try going to Rails/Django -- I keep coming back to Laravel. W/ Laravel + composer PHP finally grew up, wordpress is a hacky out-dated should-be-shot-and-replaced beast. The best way of modern web dev in my opinion is to use Vue or Angular for the frontend, and laravel as a backend. PHP 7.0 is extremely fast and proficient, and it's an easy framework to pick up.

If you need anything more resilient server side then I'd recommend using a Golang or Elixir framework like Phoenix which has multi-threading.


Could you elaborate a bit on what you prefer about it? I've heard this from a few people and would be curious to hear it fleshed out a bit.


It has most of the OOP things that I want in a language (interfaces for one, looking at you python), few things still missing but hopefully coming soon (generics, nullable typehints). And it has sane nulls in my opinion, compared to Java at least.

In the end good PHP code ends up looking like good Java code I think. But you don't have to worry about everything being nullable.

But then horrible PHP code is something else... Luckily I don't really have to touch that very often.


> As my PHP fluent colleague said to me - don't bother learning PHP or you will end up having to fix (our) Wordpress sites and thats a nightmare.

This is my life right now... lol

It's not so bad, but the frustrating part is when I talk to people in interviews about all of the great work I'm doing modernizing (the surrounding) WordPress infrastructure and the tools I've built for it, their eyes just glaze over.

I frequently get told "you're a talented developer and you're wasting your time working at X". Well, at least at my job I get to remove technical debt constantly. I don't feel like that's the case at these places I'm interviewing.


Which is a shame. I recently started toying with C#, and most of the syntax is eerily similar to PHP7. Obviously the standard library is completely different, but so far I'm right at home with the core language (though I haven't explored more advanced features yet).

Luckily I'm currently working with a PHP7 app, so all is good, but my next app will likely not be PHP at all.


This is true, it seems like the different languages are starting to converge. C# and Java are converging as well. There are still major differences, but it's getting to be like bickering siblings rather than comparing unrelated strangers.


> over engineered and almost looking like Java (just take a look at the latest Guzzle PHP Library)

Guzzle doesn't look that bad. It looks like requests from Python, but you have to create a client first.

> $client = new Client(['base_uri' => 'http://httpbin.org']); > $response = $client->get('http://httpbin.org/get');

Or in Python

> response = requests.get('http://httpbin.org/get')


My day job is no longer to write code, but I have a couple of projects I work on at night, so take my opinion for what it's worth. I have one project that's mostly static content and a couple of calculator forms. On submit, I an ajax call to post to a PHP script, it returns a json object with some data, and I display it. When I see PHP getting ripped, I always wonder, what am I supposed to use if not this? I know this is relatively simple, but my choices were to do the calculations in javascript or let PHP handle it - and PHP seemed to me as the right choice because I eventually may want to capture some of the input data, send it to a db, etc.


Basically any other backend is equivalent. Javascript (on the backend), python, ruby, anything.

Not a knock on php on my part, PHP is equally suited.

I would have personally probably chosen Flask (python).


My understanding is that the majority of PHP jobs out there are maintaining old, outdated, and bad codebases using an old version of PHP so a lot of people just don't bother.


There is probably some truth to this. Every single contract I have been offered in the past 2 years including the one I am currently working required PHP5.6 & 7 knowledge, git, composer, JS, the latest JS frameworks, etc. Start the job... PHP5.3 codebase w/ some old jQuery. Its an absolute nightmare. I have to go home at night and write in PHP7 just to maintain some level of sanity or I'd have to cry myself to sleep. The only thing that makes the job tolerable is that I was able to load xdebug on the dev environments (though it doesn't always work b/c of all the redirects - it still is good enough to get me 90% of the way there).


There have been surveys if a bit out of date:

Poll: What's Your Favorite Programming Language? (2012) https://news.ycombinator.com/item?id=3746692

Poll: What's Your Most Disliked Programming Language? https://news.ycombinator.com/item?id=3748961

https://i.imgur.com/toGKy21.jpg


Someone should start another "what's your favorite language" poll. A lot of currently popular languages weren't even on the 2012 poll at all, (like golang)


Swift wasn't even released back then


Ordering languages and frameworks by amount of 'love' (edited with small adjustments):

  ***** Python, Rust, Lisp
  ****' Go, Swift, C, PostgreSQL
  ****  Elm, Elixir, Typescript, Haskell, OCaml, JS-ES6, Kotlin, Crystal
  ***'  Scala, Lua, Clojure, Erlang
  ***   C#/.NET, Java, C++, Ruby, JS-ES5, MySQL
  **    Node JS, RoR, Meteor, MongoDB
  *     PHP, VBasic, Cobol, Coffeescript


I might rank the love for Elixir higher. Go has a lot of detractors, in addition to the people who are getting a lot done with it. Comments often seem to think Haskell or its community is a little ridiculous. Lua always gets positive comments, maybe a 3.5.

If we're including MySQL and PostgreSQL, SQLite should be way up there based on the universally positive comments. MongoDB might be ranked too high at 2, though people have begun to acknowledge that was because they tried to use it for the wrong task.


Add:

* * * * * WASM

Dare to question the pragmatics of diverging web dev practices into a whole new realm of complexity and drown in downvotes - and a litany of people being downright personally insulting/condescending. This is sort of a corollary to JS being * (I think you ranked ES6 too high) and I've been inured to people hating/ranting against JS to a point - but even I was shocked by the personal rancor that oozes out if you try to have an objective discussion about whether the web really needs one more language.


I agree, it would be more reasonable to rank JS-ES6 and Kotlin with 3.5* instead of 4. And Go with 4* instead of 4.5*.


If PG gets 4 stars, I'd put MySQL at 2 or 3 based on all the comments that show up in MySQL stories: "Why didn't they use feature X in PG?" "MySQL kicked my dog and cheated with my significant other", etc.


But you writing this as a bad thing? It's normal for a community to pick tools/solutions that are preferable.

A lot of HN users are for example startup owners/creators so it's normal that they will prefer easy and semi-automated language like Python.


It would be interesting to hear from people maintaining code that came from these startups. I suspect they would have a very very different view of things :)

Maybe something investors should think about? Ehh, who am I kidding...


This simple code and more time on hands to spend on promoting = successful startup. No one really cares about scaling YT-like app when it has 10 users.

Developers will handle that. And if they want jobs, startups must be made. As you might know, successful startups are made by less technical people mostly...


Maybe all your C#/.NET/Java devs can't access HN because their big enterprise businesses have security policies which have blacklisted it? Hah.


.NET/Java is to pay the bills, and we vote for the fun stuff while we create our boiler plate classes.


Exactly. My fun language at the moment is Clojure... I think several years of Java development has made me seriously hate OOP.


I would say that node.js is very liked on HN. Half the stories here are about Node.js.

But I rarely see any positive mentioning on HN about c#, .NET, C++ or Java.


> Half the stories here are about Node.js.

I think that might be a slight exaggeration. At present, zero of the stories on the HN front page appear to be about Node.js.


My last ten coin flips were heads, but overall, heads is roughly half.


The HN front page is 30 items. Of those, none were about Node.js when I made that comment. Right now, none are about Node.js and, though I don't trust my memory much, it's a largely different selection of items.

If half of all HN front page items were about Node.js on average, the probability of getting (let's say, conservatively) 40 with none about Node.js would be (1/2)^40 or about 10^-12.

Of course people exaggerate and I am fallible. If 30% of all HN front page items are about Node.js on average, the probability of getting at most one such item out of 40 is about 10^-5. Which is, y'know, still much less likely than ten consecutive heads when flipping a coin.


Those are the unsexy, but get-shit-done languages. I would hazard a guess that most people are familiar with them, and either are currently, or have in the past, used them for their day jobs. But they are on the plateau of productivity, rather than the peak of inflated expectations or trough of disillusionment, to use the Gartner model.


MS languages are used a lot more in large corporate style environments, while HN is startup focused where people are using open source more.


Rust should then get 6 stars judging from unparalleled excitement every news about it brings here. Rightfully so in my opinion. By the way, it's "Clojure", not "Closure" and what happened to Scala?


I have actually wondered that myself (Scala). I was so excited about Scala years ago (2006). One of my TAs from college was working on the language as well. It finally looked like an OCaml for the masses.

Over time my excitement changed. I assume others may share my thoughts hence the less excitement:

* It is on the JVM and there are lots of languages on the JVM competing with Java.

* While the fusion OOP + FP fusion is interesting I have grown wary of kitchen sink languages. There are so many ways people write Scala. Scala from one project looks vastly different.

* The endless DSLs

* Java 8 is often good enough. Particularly for interop and community support.

* Every time I have to add Scala to a Java project I'm thinking here comes 9MB jar that some classpath scanning thing is going to take its sweet time on (Spring, Servlet 3.0, etc).

But I think most of the reason is Rust has filled that hard core typers niche with the added novelty of unique memory management and competing with other LLVM languages instead of JVM languages. Scala has become "old" like Java and OCaml :) .


I kind of wonder how these points are true today vs. 10 years ago ...

* It also compiles to Scala.js (it's actually the independent best compile-to-JS language out there in terms of libraries, tooling and IDE support). Support for compiling directly to native is coming around nicely.

* Scala is quite far away from the kitchen sink, and many of the questionable parts have been deprecated and/or removed.

* I have never seen much DSLs while writing Scala. Sure, it's probably quite nice, but I have rarely seen endless DSLs in practice.

* The jar is around 4MB (2.12) and when writing idiomatic Scala (~ not Spring/Servlet) there shouldn't be any kind of reflection or classpath scanning happening.


Hmm I guess they have been actively shrinking the jar (it isn't 4 megs but ~5.5... still a massive improvement [1]).

As far as kitchen sink I'm still not sure what idiomatic Scala is especially with the likes of Scalaz. Maybe modern Scala is finally abandoning the OOP fusion.

Of course my biggest reason of not liking Scala is completely arbitrary and almost illogical (of course most reasons to (dis)favor things are arbitrary). If I write in an FP language I hate using curly braces. I prefer Haskell, OCaml, and even Lisp syntax for FP. For some reason curly braces makes me think hmm imperative shit. Not to mention Scala has lots of scoping and closure use so you see lots of curly braces.

And that brings me to another point. Scala code isn't really that much more compact (lines of code or even compressed size) to Java 8 (compared to Haskell or OCaml).

[1]: https://mvnrepository.com/artifact/org.scala-lang/scala-libr...


Maven Central says it's around 4.4MB (with some things still pending to be dropped before the release of the final version)[1].

[1] https://mvnrepository.com/artifact/org.scala-lang/scala-libr...

I would disagree with the comment on verbosity compared to Java 8/Haskell/Ocaml. Most of the things I do regularly in Scala would require a magnitude of more code. Ocaml doesn't even have higher-kinded types or implicits, so I don't think it can win much on that front (except of saving a line where Scala's curly brace might be). With Haskell it really depends. There are certainly ways to write much more succinct code, but what I see in practice is that it's not that much different from Scala. Haskell has it's own unsolved issues though: broken typeclasses, lacking module system, poor tooling, and a weekly-changing, terrible dependency management.


I'm not sure I like implicits as for HKT... "with great power comes...".

HKTs are great for a generic library writer (aka standard library) but I think the over abstract nature ends up confusing your average developer. You basically have your type aficionados obfuscating the codebase for developers who can barely handle generics. It is sort of analogous to using massive reflection / meta-programming in scripting language (albeit far more safe).

Being extremely implicit and abstract comes with a cognitive load.

OCaml's Functors (ie super strict and explicit) on the other hand can get massively repetitive.

I vaguely remember HKTs being expensive compile time. Is that still the case?


> I'm not sure I like implicits

I think they're a necessary evil. I need extension methods, ad-hoc polymorphism, and a way to use ad-hoc polymorphism while still writing nice DSLs (i.e. what spray calls the magnet pattern). I'm nervous about implicits, but I haven't seen a better solution.

> HKTs are great for a generic library writer (aka standard library) but I think the over abstract nature ends up confusing your average developer.

There are few things more frustrating than having to copy-paste because your language can't handle the abstraction. There are less cases where you need HKTs than where you need basic generics, sure, but sooner or later you do need them. And since everyone hates copy-paste, they end up using annotations or reflection or string-based templating to generate code, all of which end up more confusing to the average developer. At least with HKTs you still have ordinary values that follow the rules of the language, rather than wondering whether you can still factor out a common method because it's called from an annotated method and an unannotated method, and what annotations you need to put on it to make that work.

> I vaguely remember HKTs being expensive compile time. Is that still the case?

HKTs per se are not expensive. Type inference in the presence of HKTs can be expensive (though note that even in OCaml or pure ML there are pathological cases for type inference - http://cs.stackexchange.com/questions/6617/concise-example-o... ). Scala implicit resolution can be expensive especially when used with recursion; global-uniqueness constraints a la Haskell typeclasses would be one solution, but arguably introduce more trouble than they're worth. One way or another, Scala compilation ends up being pretty slow, which is unfortunate.


The great about types in Scala is that complex solutions to complex problems can be contained and don't infect the rest of the codebase.

The average programmer can enjoy completely consistent names and signatures across different libraries, without having to know that the consistency comes from one method being applicable to various types, not manual labor repetitiously adding the same method to different types which can drift apart at any time without anyone noticing.

HKTs are not that expensive. Slow compile times are usually caused by people doing Prolog at the typelevel in Scala.


I think Scala's still growing - I think OCaml is too. I'm worried that between Dotty and the focus on Java 8 support in 2.12, we've gone far too long without improvements to Scala syntax, or indeed a new release at all. Having written Scala professionally full-time for 4+ years I couldn't stand to go back to a language without higher-kinded types, which pretty much means I'm stuck on Scala or Haskell.


HN has language preferences, sure. Of course it does - people have language preferences, and some languages really are better than others - no wonder our aggregate likes some languages more than others. I don't agree with every specific of your star-rating, and a more objective measure would probably be more useful (I'm sure I've seen charts of which topics are popular or not on HN), but of course HN has preferences. Why wouldn't it?


Interesting that you rate RoR lower than Java and .NET. My perception is that there is a lot of bashing of the latter two. Personally I do like Python, Rust and Go and I'm curious about Swift. So there's one "data" point. :)


Any bashing of C# is always because "Micro$loth" was involved with it, very rarely is it criticized on its actual features or tools. (And when it is, the criticism is usually something like, "it's too much like Java", which I don't personally see as very damning.)


Javscript (I assume you mean) just one star? Then why 90% of the projects on the frontpage are js-based?


Node.js is a JavaScript runtime, not a language. Used for server-side JavaScript and web frontend build pipeline.

Replacing Node.js with JavaScript doesn't help either as the frontend vs server-side vs npm ecosystem vs es2015 becomes a loaded question .)


You forgot one:

    Lisp    *****


This is so true. I often think that people only need to put the word 'Rust' into the title to get a ton of up votes. Maybe because rust is a great game as well as being a popular programming language ;)


Elixir is exciting because it's making the amazing world of Erlang accessible to mere mortals with a developer experience on par with Ruby.


That's close to my perception. If you gave one of Python's stars to Ruby and RoR, gave two of Go's to Elixir and created an entry for Lisp with six stars, it would be pretty much exactly what I'd estimated from this site.


Surely measurable ? perhaps github stats are indicative - http://githut.info/

Anecdotally I would have expected Javascript to be near the top of hours being used.


What I find interesting is that we are so quick to follow new trends.


Isn't there a psychological aspect to this - that if you are on the cutting edge of languages/frameworks, that you believe you will have an edge over everyone else and a chance to be better for a period of time at least? This is of course typically ignores whether the cutting edge can actually solve problems better than mature languages/frameworks.


Psychology or survival? How much demand is there for someone who's maintained an MFC app for the past 20 years?

This person could ROCK at C++, but who's going to look at his resume and give him an interview?


Psychology is a very broad area. We all want to be part of something, a community or culture, especially one witch is highly regarded among our peers.


While I generally agree with you, I'm not sure Python is a new trend.


I had an opportunity to learn Python around 1996, and I passed. When I came across it again in 2003 I tried it, then kicked myself for not jumping on the bandwagon earlier.


1) Speak for yourself 2) Python's from 1995


And in /r/programming, anything that isn't Python, C, C++, C#, Java, Rust, and sometimes Haskell gets hated on and labeled as "hipster" and terrible.


    Julia *****
(or maybe that's just my opinion :-)


One obvious problem looking at your list is that PHP is ranked so low. This is likely due to the fact that most discussions on this site are not about PHP, but PHP frameworks like Laravel, Symfony, Zend, etc.



Nobody said all.. and your link is just some guy's rant. He mentions at the end that he doesn't have any conclusions and he just assumes that people who read the article agree with him.

Sure, PHP has it's faults, but as your article points out, it's designed to give people who aren't full time programmers tools with which to build websites or scripts to perform tasks, and there is a large market for that sort of thing.


> it's designed to give people who aren't full time programmers tools with which to build websites

And just like that, the cyber-security profession was born.


That's not necessarily relevant. It's been rebutted point by point http://forums.devshed.com/php-development-5/php-fractal-bad-..., and PHP has undergone major changes since that was written.


That PHP has gone through major changes matters, and I agree that newer versions of PHP are huge improvements, but I don't think that response is an adequate rebuttal of the Fractal of Bad Design article. The "rebuttal" is closer to apologetics, and it starts out by basically denying the idea that language design matters.

Admittedly, the author of that post lost me pretty early on when he said that languages don't need to be predictable, it's on developers to learn everything about how and why a language implemented things they way they're implemented, and complaining just means you're lazy. Sorry, but when I can guess at syntax in Python or Ruby and be right(because the languages were designed to be predictable and consistent), I don't want to consult arcane documentation in PHP to figure out why things don't work the way I expect them to work.

The author is also pretty rude and flippant, often when he's not even right. He ignores things like the Fractal author explicitly saying that Wikipedia and Facebook have very smart developers, so he can say that the PHP "community of amateurs" comment was about those developers. Pretty disingenous.

He repeatedly complains that the author "doesn't understand" "loosely typed" languages, but never considers that maybe the author understands them but thinks they're bad design, hence the whole "fractal of bad design" in the name of the post?


No D in your list?

/ goes to a corner to cry...


Node.js isn't a language.


I switched to writing python as my main backend/scripting language with my new job. Previously I was using Ruby for most of this stuff with some Go. I must say that so far Python has been a vastly inferior experience for me. The languages are fairly similar all though I prefer the more talkative/english style of ruby and the use of functions over list and dict comprehension.

The thing that really stands out to me though is the poor state of python tooling and the library ecosystem. Having used Rubygems and bundler pip feels like taking an enormous step back. It's much less expressive. It doesn't handle the difference between production only dependencies, regular dependencies and development only dependencies in a good way. It's difficult to differentiate between locked dependencies vs desired dependencies(the Gemfile/Gemfile.lock distinction). PyPi and especially using private PyPi registers is more complex than it is in Ruby. There seems to be fewer nice libraries and they seem to be spread across the web whereas Ruby centralises around GitHub. I also find that Python libraries have lacking or hard to find documentation in many cases.

I wonder how much of this is due to the community spending a lot of time on the unproductive Python2/Python3 debacle instead of moving the language and the ecosystem forward. It seems like Ruby and Python would be in more similar positions had it not been for the problems around the Python 2/Python 3 upgrade. Ruby had the risk of a similar problems in the 1.8 to 1.9 upgrade, but it seems to have worked out better than the Python 2/Python 3 upgrade.


You bring up a good point. I'm in the same boat as you in terms of switching from Ruby to Python. Unlike you I've really enjoyed the switch. But also unlike you I've chosen to ignore (i.e. stick my head in the ground) the issues with the dev-tooling. Not that I ever had a strong understanding of how Rubygems worked, other than knowing why I needed to do `bundle exec rake [etc]`. But I've largely delegated the pain of Python package management to Anaconda. Also, I haven't had to deploy any production public-facing apps in Python.

I don't share your experience on the documentation of libraries though. I've generally had no problems working with the major third-party libraries (requests, python-dateutils, Flask).

And I also am reluctant to feel strongly against how the 2v3 chasm has been drawn out, though it's easy to say that as someone who didn't have to make the jump. The main difference from Ruby 1.8->1.9, AFAICT, is that the Ruby community has a near-monolithic devotion to Rails. When Rails left 1.8 behind, not making the jump would basically be career-suicide for a Ruby dev. The downside is that it shows how dependent Ruby is on Rails' momentum. Whereas in Python, a scientist (among several other use-cases) can live on 2.x for a very long time no matter what all moves to 3.x.


python had the opposite problem where so many major libraries didn't take make the jump to Python 3, so even if you really wanted to use Python 3 it was extremely restricting to do so.


I find chained enumerator / block style code much easier to write and understand than list / dict comprehensions too. It's probably the single biggest thing that I don't like about Python; lambdas are simply too awkward, but lambdas + monadic transformations are probably my primary mental abstractions for writing software these days.


With itertools and functools you should be able to program in that style just fine. You'll likely want to give your lambdas names with a "def", but you should be doing that anyway.


Giving my lambdas names is exactly what I don't want to do - the syntactic overhead is what kills the style, makes it an exercise in boilerplate. It's like Java closures before Java 1.8 - anonymous inner classes implementing interfaces are technically just about enough, but in practice entirely deficient, because the style is entirely unidiomatic.

The way my brain works (at this point in my career, 25 years of programming) is just against the Python grain. I think in terms of data flow graphs. Python wants me to think in terms of procedures and loops.


There are very good reason for naming functions (and ideally dangling them from the class rather than making them inner functions) - this encourages you to separate the 'what' from the 'how' and tends to result in code that is self-documenting. When you inline all your functions the person reading the code is forced to build and maintain multiple abstractions at one time to follow execution flow. Additionally, you are conflating the 'what' and the 'how' which forces the reader to context shift. If you replace the function with a well-thought-out name, code becomes much easier to read.


As a fellow FPer who does the monadic stuff in other languages, I think it's usually more trouble than it's worth in Python. Instead, trying to use more of the python-specific language constructs can help you get what you want.

Python is pretty imperative, and the language design ethos is pretty against designing around functional programming. But if you try to absorb some of the python-specific stuff like list comprehensions, generators, and context managers, you can write some tooling to help you get a DSL a little closer to what you're used to.


Could you give an example of that?


Imagine you have a list of products with prices and you want to calculate the cost of all products that are of a certain type. In ruby you can write this as

products.select { |product| product.type == 'x' }.map(&:price).reduce(:+)


And in Python you can write something like:

    sum([p.price for p in products if p.type == "x"])
Excuse untested code from phone, but I like it better than the ruby version.


I find the order of iteration in Python for comprehensions totally confusing every time. If you want to convert:

    for a in x: pass
into a comprehension, you write:

    [pass for a in x]
Simple, right? So to convert

    for a in x: for b in y: pass
I obviously write:

    [pass for b in y for a in x]
Bzzt. Nope, you have to write it in middle-endian order to get the same behaviour.


FYI, you can leave off the square brackets for a small performance boost. That turns it from a list comprehension into a generator expression, which is lazily evaluated and doesn't create a list container (which would immediately be thrown out anyway). It's like the difference between range(n) and xrange(n).


Nice, thanks for the tip.


I guess it's a personal style choice, the Python code is more performant(less iterations over the data set), but I like the ruby version better.


It's only one iteration if you throw a .lazy in there:

products.lazy.select { |product| product.type == 'x' }.map(&:price).reduce(:+)


Think: bash shell pipes. Transforming input to output through successive filters and projections, applied in a concatenated fashion and developed interactively in a REPL. Model algorithms as transformations or compositions of the same, where possible, applied to lazy or eager iterators or consumers (the dual of an iterator, that acts as a sink for output) as required. Model data sources and sinks (like databases and network streams) as iterators and consumers. Program by building a data flow graph out of increasingly sophisticated (by composition) stateless widgets, rather than imperative loops etc.


I prefer Python over Ruby as a language, but you are correct

gem ist superior to pip. Take a look at "pip-tools" if you haven't already, it eases some of the pain.

For web-dev Rails is more stable, more modern and has better maintained library ecosystem than Django. Django is okay-ish but can't live up to Rails. Django still lacks some stuff that i feel it should bring with it out of the box.... dev/test/production setups, asset compilation etc.

On the other hand, if you don't need a full blown web framework and are looking for something more minimalistic, Flask is awesome.


Amazing that Python 2 vs. Python 3 has still not yet been sorted out. I dipped my toe into Python a couple years ago when looking for a general-purpose scripting language and quickly gave up in frustration—Python 3 was by far the preferable flavor, but many libraries simply didn't work. I picked up Ruby and haven't looked back.


Likewise...and when I have to work in Python it's a frustrating pain because the tooling is so much better on the Ruby side.

Heck, the tooling is better on the PHP side even...


A lot has improved since a couple years ago. A majority of major libraries have both Python 2 and 3 support these days. I've since started all new projects in Python 3.


i started with python when 3 dropped in ~2008.917

ignorant of any prior ecosystem i just thought i was getting into the most current

i came for the prebaked arbitrary precision floating point arithmetic and now i use it for prototyping all of my projects, and all the other stuff that i would call general scripting

this 2to3 complaint made sense to me from an employed standpoint:i work as X and use 2.7's Y library; but you said general scripting

i wonder what libraries were you hoping to use but were unable, and for what general scripting purpose?


This was back in late 2013. My general scripting had to do with automating wireless network simulations to explore parameter spaces and slicing & dicing results stored in MySQL or SQLite databases.

I recall several showstoppers in Python v3 including integration into Emacs, accessing a MySQL database, and basic visualization. The library system was also a mess. It didn't seem possible to develop on v3 and expect that the libraries you needed would be available. Or that anyone else would care since they were all using v2.7.


I think a lot of this is due to these problems being solved through standardised processes in python.

For example, with dependencies, production dependencies and dev dependencies are defined through two requirements files: requirements.txt and requirements-dev.txt. requirements-test.txt for testing. No need for tooling, just pass those into pip.

Most python tooling is pretty limited in scope but works well. From my side, I've had more trouble with "turing complete tooling" that ruby has offered me. I have not had to use ruby a great deal though.

I think the difference in philosophy between the two communities is that python stuff will usually value ease of debugging/implementation over "ease of use". Most things in pyhton and its echosystem are straightforward. None of this "Library A adding methods to classes of Library B" stuff (not that it's impossible). Of course, you then end up with more boilerplate.

Py2/Py3 has definitely been a major pain.


Yeah the requirements-{group}.txt convention kind of works, but what happens if you want to save only your frozen test dependencies for example? If you are using a single virtual env you end up freeezing everything in that env not only the test dependencies and its transitive dependencies.


I wish Ruby had the math and scientific library support of Python.

Also, I've been using Jupyter lately to brush up on data structures and algorithms. It's been pretty sweet to write code in a web notebook and render output including digraphs beneath each block of code. Is there anything like that for Ruby?


You can use other kernels in jupyter notebooks. I've never tried ruby, but you could try this: https://github.com/SciRuby/iruby


Not only does Jupyter have Ruby support, but you can go back and forth between languages in the same notebook while sharing a context.


Not to my knowledge and this is definitely an area where Python is a lot better than Ruby from my experience. My comment pertains more to web development than scientific computing.


You can run a Ruby kernel in Jupyter - https://github.com/SciRuby/iruby


> Having used Rubygems and bundler pip feels like taking an enormous step back.

Personally I moved away from relying on language specific tools to do more than just "install library X" and manage my deployment and dependencies using docker. So far it works great for me.

> There seems to be fewer nice libraries

Depends on your domain. Ruby is very good at web development. Python is good at almost everything.

> Python libraries have lacking or hard to find documentation in many cases.

I didn't use Ruby, but JVM languages or Javascript don't come close to Python in the documentation coverage. Especially if you consider SO as a documentation, googling "how do I do X" in python usually gets you on the right track to the high quality solution. Javascript or Java SO post are more like a mine field in comparison.


Did you take a look at pip-tools ? It allows dependency locking


What do you guys mean by dependency locking? What I do with pip is add a requirements.txt with things like:

Django~=1.10.0

And it keeps the env autoupdated with the latest patch revision but not the latest minor revision. pip-tools doesn't seem to do much related to that, no?


The problem with that is that you no longer have reproducible builds. If you checkout a year old commit and built deployment artifacts with it you want the resulting artifact the be the same as when it was created. This is what you get with Bundler and the Gemfile/Gemfile.lock split

You put

gem 'rails', '~> 4.2.7'

in your Gemfile and when you run `bundler install` the exact version of rails you ended up resolving with the above is locked in your Gemfile.lock. Thus if you have a version in Gemfile.lock it is the source of truth and you have reproducible builds. If you want to update rails given the pattern in your gemfile you just issue `bundle update rails` and it will update to the latest conforming version and update your Gemfile.lock

The fact that pip doesn't support this in a good way is a major limitation imo. You can have either reproducible builds or "auto upgrading", but not both. pip-tools solves this, but requires you to use a different tool than pip and by extension you have to teach and explain it to anyone working on your project.


I version my docker images. Inside the Dockerfile I usually install the latest version (i.e. pip install without specifying version). By single version bump of my image version I can trigger update of everything.

If I check out an old commit I can look up docker image version in the source control, download exactly the docker image that was running at that time and start shell in this image. Inside the image I can run "pip freeze" to check exact version of each package that was running at that time. I can then update the old Dockerfile with those specific versions by adding the "==x.y.z" e.g. "pip install oauth2client==3.0.0" in the pip install to reproduce the old build.

Additional benefit is that such scheme works for system packages, or for any other language libraries I can think of.


Yeah that's what I mean by either reproducible builds(e.g locking each dependency to an exact version. Output of pip freeze) or what the GP is talking about which is specifying a version pattern.


I always though the recommended way to handle that split was by using setup.py as the Gemfile equivalent with very loose versioning rules, and for the Gemfile.lock case to not edit requirements.txt but to only generate it from pip freeze (or whatever it was - I haven't used Python for a while).


Yeah I've heard people say this as well, but from my understanding setup.py is more aimed at libraries than end user projects. I¨ve never seen anyone use setup.py for an end user project in any case.

Interestingly enough in Ruby it's the reverse, you use gemspec for gems which doesn't have the concept of locking. Instead you are supposed to specify semver conforming version patterns and then resolution of these happens when the gem is installed. Only end user projects use Gemfile.lock


> You can have either reproducible builds or "auto upgrading", but not both.

Ah, okay, this crystallized it for me, thank you. Other commenters were talking about one or the other as a limitation, which confused me because pip does do both (just not at the same time).

Yes, this is currently a limitation, and pip-tools seems to solve it. Hopefully pip will get a native solution soon.


"There seems to be fewer nice libraries and they seem to be spread across the web whereas Ruby centralises around GitHub. I also find that Python libraries have lacking or hard to find documentation in many cases."

Could you clarify a bit more on this with the real world examples ?


Well for the case of "nicer libraries" I suppose I mean high quality libraries. Also good to note that I am referring to libraries in the web development/backend sphere here. I have a hard time thinking of some real world examples of there being a larger quantity of quality libraries for ruby, it's more a feeling that I get.

Around documentation and usage I think it comes down to the fact that for Python libraries a google search usually takes you to the modules page on the PyPi registry, to a project website or a read the docs instance. I usually find that where ever I end up doesn't provide all the information I want, e.g what's the latest version, what are some typical use cases for this library. As a concrete example let's compare Flask and Sinatra.

For both Flask and Sinatra a google search gives me their respective websites as the top relevant result. In this case I find both websites don't really provide all the information I am after. When I navigate to their GitHub page however the difference is more stark. Sinatra uses GitHub flavoured markdown to render a nice guide with increasingly more complex use cases. Flask just has some non markdown text pointing me in a few different directions. I could probably find all the information I need to setup and use Sinatra from just the GitHub Readme whereas for Flask I'd have to go navigate their read the docs page where all the documentation and usage instructions are spread over multiple pages and sub pages. I guess it comes down to my preference for the more concise format of a long markdown README.md vs the experience with a read the docs like set of pages.

I recon this is a bit rambling, it's kinda hard to put into words what my feelings around this are and why I hold the opinions I do.


Check out conda sometime.


That looks interesting, I've also tried out pip-tools[0] which is really nice. However nice these tools are it seems to a bit at odds with the Zen of Python. Ideally there should be just one single good way to deal with packages. Ironically this is the case for Ruby, but not at all for Python. Ultimately you can always use some alternative method that solves it better, but you then have to take on the burden of convincing your co-contributors that it is a better idea than using pip and you also have to explain it to anyone that joins your project.

0: https://github.com/nvie/pip-tools


It can conflict with any native Python installations. So if you are running any pre built Python libraries which point to any system wide Python, it can be a nightmare. Hue is one example I ran into.


Now that I have a chance to ask: I've always found the def __init__ method with 4 (!) underscores one of the ugliest things I've seen in a programming language.

Don't get me wrong: I like Python and know it's truly good, but __why__??


"The use of double underscores to indicate "magic" words goes at least as far back as the C preprocessor, which used that convention starting in the 1970s (e.g., __FILE__, __LINE__). It did so because there were no symbols that were off-limits to the preprocessor, so a rarely-used naming pattern (multiple underscores and upper case words) virtually ensured a lack of conflicts."

http://programmers.stackexchange.com/a/228340/84451


There was a technical reason for C though, the preprocessor is just a bit more than an automatic text replace, in Python it seems it was just a design decision. Also in C those where not words embedded in the language, in python case it is.


Call me ignorant, but I agree. Having something like __init__ and __new__ is very confusing for a beginner, along with stuff like "__init__.py".

It doesn't stop there: Take something like __str__ and __repr__ combined with str(), repr(), vars(), dir(), print(), pprint.pprint()... I have no idea how anyone ever thought it was a good idea to have that many ways to output the content of a variable. Even after all the time I used python I never managed to find a consistent way to output variable values.

I generally like python as a scripting language. But stuff like this made me constantly lookup obscure details in the documentation which made it very hard for me to completely embrace the language. It also prevented me from diving into more arcane stuff like meta-programming...


The dunder functions are there to provide an interface to global functions and operators.

If you want to affect how str(x) behaves, you override x's __str__() method. Operators behave this way too: for example, if you want to overload the == operator for a class, you override __eq__() in that class (for any Java developers reading: Python == works like Java equals(); the Python version of Java == is the is operator, which cannot be overloaded). Yes, that means x == y is just syntactic sugar for x.__eq__(y).

The dunders are there so you have the freedom to name your methods what you want without having to worry that you'll accidentally clobber a method that affects a global or an operator, as most people won't just up and decide to both begin and end a method's name with __.


> combined with str(), repr(), vars(), dir(), print(), pprint.pprint()

Very true! Though since in practice, most people simply use a graphical debugger or pick one of the above as their champion (pprint.pprint is my personal favourite), then I doubt this situation will ever be changed.


It is a convention for protocols. There are others you see __len__, __eq__, __new__, __str__ and so on. It did seem odd at first (I learned, C, Java, C++) first. But then after a while saw how it fits in a consistent way in the language. Make many things simpler, fits with duck-typing, fits with how classes are constructed, and so on. Visually it stands out right away, you so you know by looking these are special methods (say instead of being called "init", "eq" or "new")

Felt the same way about "self" argument. But then now I really like it and see it as a very nice idea.


Agreed. That, the explicit self argument (which no other major OO language needed) and the : at the end of lines where you would need a { in other languages. If you google you find that there are good reasons for all of those choices but IMHO they are wrong solutions to the problem they solve and make Python look ugly. At least in 2016 they could make the colon optional.

The colon is so ironic for a language that takes pride in replacing braces with indentation. It's there because of readability, see https://docs.python.org/3/faq/design.html#why-are-colons-req... but so, how about an almost Erlang-like full stop?

    if condition:
      statement
      statement.
That would make semantic indentation optional, IDEs and editors know how to reindent code, spare us with bugs introduced by careless copy and paste.

Nevertheless, Python has been widely successful and it's here to stay for a long while. I hope designers will look at those bizarre features and think of better solutions for future languages. Remember that Python has its roots in the 80s. By the standards of the time it was very good. Compare it with the order of magnitudes worse design of PHP, from middle 90s, and there is a lot to forgive to Python. Maybe Guido Van Rossum would make different choices if he were to design his language now, under the influence of the languages of the last 20 years.


> how about an almost Erlang-like full stop?

This is just brackets/braces in disguise, at which point you might as well follow convention and use {}.

This is obviously a very personal issue, but for me, the whitespace has less cognitive load. E.g.: in languages with brackets, people usually still indent the code for readability.

I've also found that when teaching people to program, consistency works well. I think this is one of the reasons Python is easy to pick up, just because Python code consistently looks like Python.


For those languages is not people who reindent code but it's the editor or the IDE. There is usually a key to force reindentation. That is possible because {} or even the end in Ruby are easy markers for the block (there are multiple markers for a block start in Ruby). Is there any automatical indentation function in some editor for Python? If not, it's Python the unfortunate language where people has to indent code to feed the compiler. I always hated doing the compiler's job.

I'm asking because I'm using Python little and only for short scripts, so I didn't bother investigating much. Still I've been bitten a couple of times by bugs introduced by moving code around and not noticing that a line was not indented correctly. That in Python and in Haml (http://haml.info/) If somebody knows about those tools I will appreciate and it will make my life easier. BTW, I'm fixing somebody's else Python scripts right now :-)


> For those languages is not people who reindent code but it's the editor or the IDE. There is usually a key to force reindentation.

Regardless of whom or what is doing the indentation, people still prefer reading code which is indented, even in a language which relies on braces or parenthesis for flow. The indenting is not for the compiler's sake, it has no problem understanding this: http://www.ioccc.org/2014/maffiodo1/prog.c

Also people get very picky and personal when it comes to indentation in ways that a computer can't always choose. I prefer to almost always indent and format my code myself, rather than letting the editor choose. Python is the only language I actually let my editor auto-format, because of PEP-8.

> Is there any automatical indentation function in some editor for Python?

Pretty much any editor will have a feature for this, or allow you to install a popular plugin for it in less than a minute.


How does it know that a line pasted to the end of a block from another indentation level belongs to that block or should go after the end of the block?

    if cond:
      line
  pasted line # where does it go?


The explicit self, while clunky at first, is clear and easy to understand. Contrast this with the fun of 'this' for bound and unbound methods in Javascript, and the mysterious extra arguments like 'arguments' that plenty of people don't even know exist.


I believe it's part of the language design, a phrase you'll find quite a lot in Python language discussions, especially is more esoteric features is; "We're all consenting adults".

There are certain areas of the language which may not behave exactly the way you'd be expecting, if you're new to it.

These usually have an unusual syntax, which will cause you to find out more.

They're basically the mini-roundabouts of python.

https://en.wikipedia.org/wiki/Roundabout#Mini-roundabouts

If you know what you're doing you cruise straight over, but if for any reason you're unsure, you're forced to find out more before continuing.

It's not designed to stop you, because "We're all consenting adults", but that doesn't mean it's going to encourage you to do something that might be harmful.


Unless of course you're in Belgium where all junctions are by default preference from the right (so like a mini-roundabout but with no markings), which are opposite preference from roundabouts here which are preference from the left. But some junctions are labelled, some aren't depending on whether the local council could be bothered, some people will forcefully use their preference and risk a crash but 90% will ignore it.

Driving in Belgium - the scripting equivalent of batch files


So people don't call it directly Defense mechanism of sorts


Also limits chances of conflict with user-defined code.


The second annoyance is that you need to write __init__ methods quite often.

Correct me if I'm wrong, but there doesn't seem to be built-in support in Python for having attributes initialized by the the constructor.

For example in Perl 6, I can write

    class Point {
        has $.x;
        has $.y;
    }
... and I get a constructor Pair.new(x => 1, y => 42) for free, no need to write custom initializers.


Nothing built in, and generally not recommended, but you can do it! If you want to be really flexible and just allow any attribute, you can do this:

    class Foo:
      def __init__(self, *args, **kwargs):
        self.__dict__.update(**kwargs)
And it will automatically assign any keyword arguments you use as attributes to the object. For example `foo = Foo(name='Bob', age=99)`

If you still want to keep a strict list of allowed attributes, you can define them as parameters, and use a shortcut to assign all local variables to attributes.

    class Foo:
      def __init__(self, name, age):
        self.__dict__.update(locals())
        del self.self
So `foo = Foo(name='Bob', age=99)` will still work as will `foo = Foo('Bob', 99)`. But `foo = Foo('Bob', 99, True)` will throw an error, as will `foo = Foo(name='Bob', age=99, likes_cake=True)`. You can add kwargs back to the parameter list if you want to allow assigning any attribute.

This isn't recommended though. So for all practical purposes, Python does require a bit of boilerplate in the constructor.

Edit: Realized a cleaner way to do the second example.


I believe you could also accomplish this with a metaclass, as well.


Just import attrs [0] and don't worry about those annoying dunder methods.

[0] https://pypi.python.org/pypi/attrs/16.0.0


I use python on daily basis for 5 years now. It's a really cool language, but:

* Packaging is horrible

* Releasing python code is a non-standarised nightmare. Every solution has it's own flaws

* Big and complex projects in python are really hard to reason about

* Poor support for concurrency (fixed in py3)

Don't get me wrong, python is really cool as a proof-of-concept scripting language. But for mature and complex stuff, I'd recommend something with type checking and better support for release process.


Do you really think packaging is still horrible? I tend to agree with Glyph Lefkowitz [0]. What issues are you still having?

[0] https://glyph.twistedmatrix.com/2016/08/python-packaging.htm...


Fully agree. After spending quite some time working on a medium-sized Python codebase I went from being agnostic about static vs. dynamic typing to favor static typing. In a small side project I've used Python 3.5 with type annotations and it's an improvement, IMHO.


I've been a Python developer for years and I also agree that static typing is fantastic. I'm very much looking forward to the recent optional typing in 3.5 improving.


I've been really happy using Pex[1] for releases, but it's not 100% perfect. It definitely feels less painful than other ways of doing things. At one point I used bdist_rpm for all of my projects, and then made sure I had all the dependencies installed (also through RPM, using FPM to create an RPM if it didn't exist). It was a nightmare.

1: https://github.com/pantsbuild/pex


Yeah, I created an issue on github about the lack of support for pex on uwsgi. Proposed solution (https://github.com/unbit/uwsgi/pull/1297#issuecomment-240200...) will work, but again, this is not standardised at all. This is one big hack comparing to the way how Erlang boots up their apps. Erlang here is a good comparison, because it is much more complex and harder to learn, but it is complete in terms of release process. You don't have to hack your way out to production, just read the docs and you know what to do. Python wasn't designed to run this way, so everyone tries to create their on standard.


I've programmed in a few other languages than Python. I'm curious to know which languages you think have an easier time managing mature and complex stuff?


It really depends on the type of project that you are working on. For backend services that don't require much data processing (OCR, some complex matrix calculations) I'd recommend erlang or elixir. Here is why:

* type annotation + awesome tool for analysing code (dialyzer)

* immutability, list cannot become a dict out of nowhere

* great support for concurrency

* concept of application (OTP) gives out ability to run many loosely coupled apps on one VM. I believe "microservices" is the buzzword that matches the concept.

* distribution by design.

* great monitoring tools

* I could go on... really.


Statically typed languages. Personally, java or C#.


I've worked with large C++ projects and large C# projects (both at large software corporations) and the code was not particularly less unwieldy than an equivalent Python projects I've worked on.

I think static typing alone doesn't make managing complexity easier.

I'd like to know what other features people think Python is lacking that make it much worse than C# or Java when handling large projects.


I'm often frustrated with python packaging but after trying a few other languages' equivalents' (npm, go, etc.) I'm starting to think it's really not so bad.


Just yesterday I had a frustrating issue. Digital Ocean VM with Ubuntu 16.04 and pip 8.1.1 installed via apt. "pip install -r requirements.txt" with pinned (recent) versions failed. I think it triggered this issue https://github.com/pypa/pip/issues/3687. Didn't investigate though, since this was just a side project and it was 11pm. Made it work somehow. :-/


I'm curious as to what issue you're running into with npm? npm install pug --save , installs to your local project, and adds to package.json. Not sure how that can get any easier! Makes deployments silly simple as well, and the ecosystem is massive surrounding it.


* I sometimes had to run "npm i" twice in order to get it to work.

* It would often fail randomly.

* node_modules has a fixed location.

* There is a ludicrous number of dependencies even for the simplest projects. ~1000 is not unusual. Reasoning about that dependency tree simply isn't possible.

* There was even a package to detect if a number was negative. It had a version 2 because there was a bug!

* In general even small projects took an age to build.

I'm sure this isn't all the craziness, it's just the stuff I ran into during my (fairly limited) exposure to npm packaging.


Certainly any dependency manager has its issues, and I've run into a lot of them with other ones as well. But yes, I will agree, the dependency hell comes from requiring duplicates for each package you install. Though NPM is working on resolving that. Not sure what you mean by age to build though? What are you building after package install?


Why you shouldn't learn Python:

1. In-consistant syntax.

2. The language uses exceptions to control flow of logic.

3. Divided community, since Python 3+ included breaking changes to the standard.

4. Un-discoverable APIs. You better hope the documentation is bulletproof else the API could change in any which way during runtime.

5. Poor error messages. If an import goes wrong you are not told why, and so on.

6. Ultimately slow performance for anything marginally complex.

7. Poor tooling.


1. a matter of tast

2. care to elaborate ?

3. it's not divided, it's evolving from 2 to 3. Java's community is under Oracle's grip, don't know if it's any better...

4. it's not because you can do it that it's worth to do it, so in practice API are just not changing at runtime

5. I can say the same of my industrial strength Java environment...

6. Not a problem since what you do doesn't require speed

7. Ever used PyCharm ? I wouldn't say it's poor tooling. The debugger is fine. What I miss is something like a good profiler to look at running code.

But I'd say :

8. Optional typing should've been there from day one, it'd made code editor, tooling better

9. The date/time handling is not good

10. SOA support is weak (and in the kind of setting I am, we use tons of XSD, WSDL, XML, security, signature you name it)


#2 is because it is more "pythonic" to ask for forgiveness than permission (EAFP).

For example, rather than checking if a dictionary has an element before accessing it, you just try to access it and handle the KeyError if it doesn't. The code reads easier and the normal flow would be faster in this case.

When used in EAFP context only, I think it is fine to use exceptions as part of logic in Python. They are relatively less costly compared to C.


> What I miss is something like a good profiler to look at running code.

vprof is quite nice: https://github.com/nvdv/vprof


PyCharm comes with cProfile and let's you "run with Profiler". But maybe that's only the paid version.


Yup. The integrated profiler is only in the paid version


Reasons to learn Python:

Sklearn, tensorflow, pandas, Sqlalchemy, requests, Beautifulsoup, numpy, scipy, pulp.

If you have a language that had equivalent libraries that cover all these domains I'd love to hear it. Until then I can build really cool stuff in Python very easily thanks to the amazing hardwork and generosity of these library creators.


If you have a language that had equivalent libraries that cover all these domains I'd love to hear it.

R[1].

[1] https://cran.r-project.org/


Okay, but I'm not sure they wanted to go from python to R. The issues listed in the original post are definitely not fixed in R. And you lose out on python's ability to also be used for other things.


The problems people have with Python are magnified at least 10x on R.


You can't possibly claim that the R language is better-designed that python...


Yup. For engineering and data science Python seems to be the best choice right now.


> 4. Un-discoverable APIs...

One of the main reasons I like python is that it is the most self-documenting language I've come across. Say what you like about significant whitespace, but in my last job I used to show salespeople snippets of code and they understood them - with no knowledge of the language.


I agree that the code does document itself well. The biggest problem I have is the docstrings [1] which I find quite weird and find the Javadoc style comments much more readable.

  [1]: https://www.python.org/dev/peps/pep-0257/


>3. Divided community, since Python 3+ included breaking changes to the standard.

I'm using Python since about half a year and for all I did this wasn't an issue. I just started with 3 and had the feeling everything around me was 3 as well. 3 was released in '08.


We are hitting the 2/3 divide constantly. In our software we try to support both (for plugins). But it is a mess especially if you want to load interpreters to both at the same time. It is also near impossible to make somebody update from 2 to 3 in the scientific community.


Unless you want to follow a tutorial or use a library. Most are up to 3 now, but not all. And especially with tutorials, the older ones don't always say.


Name a single language that covers all those things and has a pretty syntax.


Scala. (Which is why I use it)


01000010 01101001 01101110 01100001 01110010 01111001 00111111 00001101 00001010?


You had me until the CR LF, but clearly the true hacker's choice is just the LF. <ducks>


Binary?


1


10010 10202 11020 11002 10121 11020 11111 01020 00101


IMHO Ruby is a good candidate.


Weird, I actually consider Pythons consistency in syntax to be a positive. And it's continually becoming more so.


What do you mean by inconsistent syntax?


Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))?

http://effbot.org/pyfaq/why-does-python-use-methods-for-some...

I guess is that.


Collection library has:

  deque

  defaultdict

  Counter
After many years I often write DefaultDict myself.

Edit: formatting


8. Significant whitespace. Not only is it a constant minor inconvenience when editing the program, it makes it very hard to cut-and-paste code fragments on the web.


"Making it hard to copy-paste code from the web" is something that I would consider a feature, to be honest.


Some similar failure cases are: 1) when I make a presentation using Keynote, it drops the leading spaces when it exports to PDF, so my students can't simply copy/paste my example code. 2) the interpretation of blank lines with no indentation on the repl means "end of current code", which is different than in a .py file. This means if I copy&paste from my in-development code to the repl, I can get syntax error unless I carefully ensure that all blank lines inside of indented code blocks are also indented.


For (2), ipython and %cpaste are your friends.


I've never understood this complaint. Whitespace is included when you copy something. What's the problem?

Admittedly it is mildly annoying when someone decides to use some random number of spaces for indentation, and you have to fix it to make it match the rest of your code (my preferred editor, Geany, has a feature for this). We should all just use tabs. But "very hard"?


The web collapses whitespace so if the code is not in <pre> tags you are stuck. This is quite often a case where comment systems were not intended to share code.


You're right, of course, this does often happen. Seems to me, though, the issue isn't cutting and pasting something on the web - it's getting it losslessly onto the web in the first place. It's the responsibility of the person posting the snippet to ensure it shows up correctly, and if their chosen platform doesn't support that they should use a better one.

This probably reads pedantically, but I do think there's a distinction. By analogy, if someone tried to post APL on a site that didn't support Unicode, you wouldn't say the issue is it's "hard to cut and paste APL".


Yes I would. Requiring a character set outside of ASCII is what I'd call a high-risk design decision, that could easily become a misfeature of a language. Windows "smart quotes" are bad enough and that's not even a programming language. This is why people invented J as an alternative to APL.


Would you say it's "hard to copy and paste Unicode"?


Most systems support UTF-8, so most of the problems have been solved by now. There's still a lot of scope for malicious or very surprising unicode; invisible characters or modifiers, font problems, RTL/LTR, characters which have different code points but cannot necessarily be visually distinguished ("ı = 1" etc), good old Zalgo, and so on.


It's Python's fault for not retrofitting its syntax to satisfy a markup language invented years later?


No, but it is a problem that people encounter nevertheless.


> Whitespace is included when you copy something. What's the problem?

In addition to the points posted in a parallel thread, selecting and copying leading whitespace reliably is more difficult than just getting the printable characters. Also: it's not something that anyone has any cause to do outside of copying Python text.


Any editor with multiline support makes this problem go away (vim, sublime)


8. Global Interpreter Lock in CPython


This isn't an issue with the language, it's an issue with the common implementation of the language. It will be remedied by either fixing CPython, or by switching to a different implementation.

(If neither happens, then I guess it isn't really a problem.)


I wrote explicitly that this is a problem with CPython. I totally agree that this is not the problem of the language itself. Neither are the most of the points from the parent post(tooling, community, performance, error messages). Yet all that still greatly affects your experience with the language. Same applies to the default implementation. I think you would agree if I said that Sun(Oracle) JVM played an important role in Java adoption, wouldn't you? Unfortunately, it's not so easy to just switch to some other implementation of Python: PyPy uses GIL as well, IronPython and Jython don't but they are years behind the current version of the language. GIL is not a problem when you use libraries that handle concurrency natively(e.g. NumPy) but when you try to parallelize some computationally intensive algorithm written in Python you're probably going to hit the wall. I love Python but it's really not a one-size-fits-all tool.


> This isn't an issue with the language, it's an issue with the common implementation of the language.

There is no formal definition of the language. It is defined by the C implementation. So I'm not sure how meaningful that distinction is.

> If neither happens, then I guess it isn't really a problem.

Or people give up on Python and use another language.


Python is not defined by its C implementation. For example, Python-the-language does not require reference counting even though CPython uses that.

The real-world distinction between the Python specification and its implementation started in the late 1990s, with JPython (now Jython).


The person who wrote this obviously has "the hacker's mindset". He praises expressivity and malleability of the language.

Well, in this case it might be advisable to take a look at Perl. And never go back. Perl (especially Perl6) is hacker's paradise, where everything's true and nothing is forbidden.

As somebody who shares the same mindset, I truly enjoyed my years with Perl, and I occasionally return to this experience.


> is hacker's paradise

And support engineer's hell


So is Python. I've worked on code bases in several languages, and the greatest horrors I've seen are in Python and C++, in that order.

Python is a strange case. The CPython code base seems to be quite well organized and well written, and about 10% of packages on GitHub or PyPI are extremely solid.

The problem is the staggering amount of packages (public or in-house) that have 100000+ LOC and use the worst features of OO, functional, and procedural programming at the same time.

The result is not spaghetti code, but ravioli code where there's zero control flow and "everything happens somewhere else". Add to that the "consenting adult" philosophy, and you have the modern equivalent of goto mixed with self-modifying code.

I'm sure Perl has all that, but it's far from the only language.


Always fun writing compact Python:

    import sys
    from collections import Counter
    
    cnt = Counter([n.strip() for n in sys.stdin.readlines()])
    
    for key, val in cnt.most_common():
        print(val, key)
This isn't just playing code golf, it goes with point (2) - awesome libraries. One of the joys and curses with Python is finding the Pythonic ways to do things that you've hamfistedly written your own way for months.


FWIW the Counter line can be simplified slightly:

    cnt = Counter(n.strip() for n in sys.stdin)
* no need for a list comprehension, a generator expression will do

* file objects are iterable, and iterated line-wise


And you can actually ditch the list comprehension and put it directly in the function call!

    Counter(x for x in y)


A new & free introduction to Python from Jake VanderPlas can be gotten here:

http://www.oreilly.com/programming/free/a-whirlwind-tour-of-...

I was looking for a dense & concise guide to the language, but one of the most popular books "Learning Python 5e" by Lutz was too long @ 1600 pages.


His book is awesome! I wish I had it when I started Python. I had gone through the documentation tutorial thrice, the entire documentation once or twice. Started writing code and then understood python.

I found that learning Python is simple, mastering it is difficult, the magic which happens all the times makes it difficult to understand, which is the reason why static languages are awesome as less magic as possible.


> Another thing is strict typing and debugging: since Python is an interpreted language, finding bugs wasn’t as easy

Wait, what? How is its interpreter remotely relevant to its semantics?

> if you have a syntax error in C, the program will simply not compile, on the other hand, in interpreted languages, the problem might go unnoticed for quite some time

Hang on--Python allows you to run code that has syntax errors? I'm so confused.


To my knowledge syntax within a file is completely checked when that file is loaded. I think the OP referred more to errors in method and other reference names.


If you write this:

  #!/usr/bin/python
  import time
  time.sleep(5)
  fdafadsfadsf
It'll take 5 seconds to crash with a "NameError: name 'fdafadsfadsf' is not defined". Likewise, if you do this:

  #!/usr/bin/python
  import time
  x = 1
  time.sleep(5)
  print "x is "+x
It'll take 5 seconds to crash with "TypeError: cannot concatenate 'str' and 'int' objects"

In a language like Java, these would be syntax errors, and they'd be picked up at compile time as they're illegal in Java's syntax.

I assume they're legal in Python's syntax, because for all the syntax checker knows, time.sleep() might define fdafadsfadsf and convert x into a string. So they're runtime errors in Python.

Of course, Java still has runtime exceptions - null pointer exceptions, for example.


Yep. What drives me even more crazy is things which are purely syntactically wrong, e.g. an else: clause with no if before it are only detected when the interpreter gets to that line.


Java and Python are apples and oranges - one is a compiled language, the other is interpreted. Better to look at other interpreted languages like Ruby & Perl...and they have the same issue. It's a side-effect of using an interpreted language, but it also allows such languages to be self-modifying which can be very powerful when you need it.


Python and Java are both compiled to bytecode and both interpreted as bytecode. It has absolutely nothing to do with compilers.


Perl actually has a 'compilation' phase where some types of syntax errors are actually detected before it goes executing the code.


Addressing some criticism from various comments:

> Python 2 vs 3

It is mostly over. All important libraries are accessible on 3. It is clear that if you are starting from scratch you should go with 3. There are good tools to help with the migration (e.g. six). Some libraries start dropping python 2 support.

> Bad tooling

Having used Emacs with jedi for a while I switched to PyCharm to leverage optional typing. PyCharm beats my tooling experience in all languages I used expect Java:

- Auto imports work well.

- Code completion works very well, especially on optionally typed code.

- Even refactoring works very well, failing short only to my experience with Java, but beating C++ or even Scala.

- Debugging is actually a highlight - I can drop into full fledged REPL at break point. "Evaluate expression" in C++ or Java didn't come close.

Profiling is indeed not as advanced as what I was used to on the JVM, but IMO it is sufficient for 95% of use cases. For that 5% it is clear from the start that you shouldn't go with python. Language specific performance monitoring in production becomes less of an issue when you start running inside containers and it starts to make more sense to monitor containers rather than individual processes.

> Maintainability at scale

I am using Python 3.5 optional typing and I feel my project is much more maintainable as a result. Among others, refactoring in PyCharm works very well.

> Packaging and deployment

As mentioned in another comment, personally I moved away from relying on language specific tools to do more than just "install version X of library Y" and manage my deployment and dependencies using docker. It have it's own problems, but so far it works very well, and it's quickly improving.

> Performance

In domain of scientific computing by using correct libraries and things like Cython or Numba you can come close to C++ performance levels. In other domains it's becoming more common to be disk/network bound, and then it doesn't matter if you use Assembler or Python. Also JITs are coming to Python: https://lwn.net/Articles/691070/.

> Syntax/libraries/language features/etc.

It is the most subjective section, but my experience with python in this regard is highly superior to Scala/Java/C++/JS.


In PowerShell,

   PS> Import-Csv .\names.txt -Header name | group name | select name, count
   
   Name  Count
   ----  -----
   cat       3
   dog       2
   mouse     1
   bird      1


Seriously, the author seems to have fairly limited knowledge of powershell.

A 13-line python script is presented, followed by a smug "you can almost hear the UNIX folks complain about how verbose the PowerShell version is".

First off, the provided Unix commands _don't work_ (should have used `sort -rn -k 2`), while the provided powershell, as verbose as it is, does work.

Second, the entire python script along with the wrapping unix commands is encapsulated with a powershell 1-liner:

    cat ./names.txt | group | sort -d Count


As the author mentioned Python is good for small stuff. If you are building a huge system where the jobs are spread between a dozen of people things could easily get out of control and you could end up in the dirt.


Do you feel this way due to the dynamically typed nature of the language (and the possibility of having ambiguous interfaces)? I've had pretty good luck with rather large scale python projects, though we've been pretty strict about working within a framework.


Yeah mainly due to that. If you don't have a VERY strict approach to writing code, one wrong decision could turn into a few days of debugging..


Where 'strict' == 'unit tested', then I agree with you. You don't need strong typing to make good code.


I would agree that complete and meaningful unit and integration tests are definitely a necessity for a large Python projects. Or really for any software project meant to be maintained.


You can write crappy code in any language. I have seen large, easily maintained systems written in Perl, and I have seen horrible little tools written in Java. There's nothing specific to Python.


Python is in space [1].

There is such a large breadth of fields that it has been successful in. Web apps, data analysis, machine learning, micro controllers, etc.

It has a long track record for being stable, reliable and secure. The popularity over the years has been steady and with the recent addition of data science field and machine learning, it's seeing another growth spike.

In my opinion, it's a highly versatile and very productive language that seems to be able to handle just about any job or industry you can throw at it. I personally switched to it full time and love it.

[1] https://www.youtube.com/watch?v=Zm08hXeuv-I


If you want to learn more in-depth Python: https://pythonspot.com


I just went with the "Fluent Python" O'Reilly book.

http://shop.oreilly.com/product/0636920032519.do

It's a bit pricey, but I managed to score it on a 50% sale, and I have to say I think it's a very good book for people already fluent in other programming languages.


If only the JVM didn't have slow startup speed I would almost exclusively write Groovy scripts.

There is just something so awesome about shoving your dependencies right in the script and not worrying about pip, easyinstall, system libraries etc [1].

Maybe Java 10 will fix the startup speed (or whenever jigsaw is done correctly) but I doubt it.

[1]: http://docs.groovy-lang.org/latest/html/documentation/grape....


> There is just something so awesome about shoving your dependencies right in the script

Groovy needs two lines (@Grab and import) to get a dependency. Golang only requires the import. Perhaps Groovy needs to be rewritten in Go.


> Groovy needs two lines (@Grab and import) to get a dependency. Golang only requires the import. Perhaps Groovy needs to be rewritten in Go.

I'm not dissing Golang but it isn't even remotely the same. A major portion of the OP content was about using Python instead of shell scripts.

Golang is not scripting language. You need to compile for each platform and the code is opaque once it is compiled. Not to mention Golang might not have dependency issues at runtime but the overarching consensus is that certainly has issues with compile time dependencies management (auto checking stuff out from github is not effective).

> Perhaps Groovy needs to be rewritten in Go.

I normally don't say this... but that is just dumb fanboy comment.

EDIT: apparently you are working on a scripting language powered by Go called Gro. I'm not sure if you just mistyped and meant Gro instead of Go.... and reading your blog it seems you must have been severely burned by the Groovy community.


> I'm not sure if you just mistyped

I didn't mistype. Go would make a good language for writing dynamic languages such as Apache Groovy in. My own Gro is just one example of such a dynamic language.


> Go would make a good language for writing dynamic languages such as Apache Groovy in

Wasn't the whole point of Groovy to have something Ruby-like that was more intimately tied into the JVM ecosystem? Seems to me that Go would be just about the worst imaginable [0] implementation language for that.

[0] Or at least, in the class of extremely poor choices that includes all languages that are not themselves especially targeted to the JVM platform.


I think his point was instead of using the JVM runtime to now use the Go lang runtime. Of course you would need the interpreter for each platform like Python does but Go has a unique runtime. I'm not sure how dynamic it is but you can certainly run a scripting language in it and make it easy to access other Go stuff.

I'm not sure how easy it would be to access ad-hoc libraries without recompile though since Go doesn't really have dynamic loading of libraries (or maybe it does now?).

Little tangental ... After reading his blog I'm a little concerned though that the dude (Gavin) has spent an enormous effort defending his stance on how poorly the Groovy organization is... I'm not saying his wrong but is almost obsessive and a waste of energy.


> I think his point was instead of using the JVM runtime to now use the Go lang runtime.

Right, my point was that a central part of the point of Groovy was being for the JVM, it wasn't a language in search of a runtime.

So, while there might be an argument that a language like Groovy for Go runtime might be useful (I'm somewhat unconvinced of that), it just seems not to be the case that Go is a good choice for a language such as Groovy (that is, it is not the case that Groovy is an example of a language for which it would make sense to use Go as the implementation language.)


> to access ad-hoc libraries without recompile though since Go doesn't really have dynamic loading of libraries

In the current version of Gro, I recompile (just like "go run"), so there's a 1 second lag even for simple scripts. For the same reason, the very basic REPL provided has a 1-second process time for each command. There's talk on reddit.com/r/golang about building a VM for Go so maybe in future Gro can use those.

> Are you going to change your middle name now to "Gro"

"Gro" is short for the "Grover edition of the Groovy language".

> has spent an enormous effort defending his stance on how poorly the Groovy organization is... [...] almost obsessive and a waste of energy

I've averaged a blog entry a month for the last 5 years. It seems like enormous effort and obsessive to you because you saw them all at once.


Yes I think I realize your point. But original it came across though like:

"oh your script can just be rewritten in Go and while we are at it Groovy should be rewritten in Go".

But yeah I would be interested in platform agnostic scripting language with out GIL, cheap threads, easy dependency access. I'll keep Gro on my radar :)

Are you going to change your middle name now to "Gro" (I did find that amusing albeit I'm not sure I know your entire history with Groovy)?


I first learned Python and then much later C, and for me at least learning Python first was very motivating because you can get things done so easily, due to the built-in batteries and the wealth of external libraries. Seeing that the computer needs less than a second for what would have taken me many hours of tedious work was pretty eye opening.

Learning C later on helped me understand some basic concepts better and being able to speed up Python e.g. using Cython can come in quite handy.


Python is so easy to write, use and read, I would not understand how a programmer would not know it already.

It literally has everything you want in a language.

Granted, it's not on-the-metal fast, and it still has some gimmicks, like variables behaving like pointers or references (which can be a little awkward), but still, python is the language of the decade.


Ugh. I tell you, I keep trying to pick it up because I hear so much about it. However, when I code in it I feel completely uninspired. I can only get so far into a book or tutorial before my eyes glaze over and I'm thinking about something else.

I think when I code, I want to own the machine, not just skate on the surface. Python doesn't even crank my engine the way BASIC did years ago.

I also think part of my problem is it doesn't solve any needs right now.


Well python is not for solving hard problems. If you want to own the machine you need C++ or C.

Python is a language that makes programming easy. That's a lot.


One my feeling about python is that is a great language for "reference". Probably everybody and write and read it and its already good enough for general programming. There are edges where other languages are better but still is a great language to establish communication among different types of developers


Yes, I've seen Python described as "everybody's second-favourite language". It's not the best at anything, but if your main requirement is a bunch of different people all need to be able to read and edit the same code then it's a good choice.


As a historical note, this phrase was originally applied to WordStar. Quoting Jim Mischel at http://www.mischel.com/diary/2005/08/22.htm :

> While I'm on the subject of WordStar, I've heard a story that I haven't been able to verify. When Phillipe Kahn was asked why he chose to use the WordStar command set in the first version of Sidekick, he said that he asked a lot of people for their editor preferences. Almost everybody had a different first preference (back then it could have been Emacs, vi, Word Perfect, WordStar, Brief, Leading Edge Word Processor, or who knows what else). But almost everybody he asked knew WordStar and named it as their second preference. I don't know if it's true, but it smacks of truth. Certainly every microcomputer programmer I knew back in the late 80s was proficient with WordStar.


Couldn't we say the same thing about Ruby?


Not really. Ruby isn't anywhere near as widespread or well supported in fields like finance, math, various scientific fields and GIS. Python on the other hand has at least has pretty good support in just about any domain you happen to stumble into.


The long history of Python support in the scientific community has produced a rich catalog of domain-specific analysis libraries. Warts and all, it's simply not possible, in most languages, to achieve the analytical productivity you get when working in Python.


I've had to deal with Python for a long time. I even wrote my senior research project with it in college.

But since then, I've never really had a need to use it, and I don't even feel there is a good reason for it.

If you're writing something more than a quick shell script or a project that will last more than a few days, then there a dozen static languages that have better libraries, more powerful IDEs, etc. And misspelling a variable or missing a comma is not going to cause all sorts of problems.

On the other hand, if you do need a quick one-off script or some duct tape, things like Perl or AWK, sed, and friends seem like a better bet.

Python (and Ruby) seem bloated for quick scripts, and wholly lacking for larger projects.


I have contemplated writing a "Why You Should Learn Bash" article and then maybe "Why You Should Learn Regex" followed by "When to not use Regex".

If you know bash you probably have a pretty good idea how to manage Linux and roughly how things work on Linux (you could apply this to other Bash capable OS as well).

If you know Bash fairly well you probably also know how to automate many things and you probably already know regex which is fairly useful in GSD. If you know Bash you obviously know the command line well.

You should learn Bash (or some shell but Bash is so ubiquitous).


The "namecount" example is rather silly though. It can be solved by a shell script much shorter than one line (sort|uniq -c).


Hey there! I've answered a similar observation in the comment section of the blog :)

> Of course it can be done all with command-line tools, but the point was not to show you how you can count and sort word occurrences. I just wanted to show that it's possible to include Python scripts in your "command line workflow". I wanted to give a simple example that would give you a taste of the idea :)


Why do programmers try to convince others which programming language to use? Why should they care what languages others are using?


The more popular your preferred tooling, the more opportunities in the job market.


I read lots of people complaining about medium-to-large scale Python projects, due to lack of static typing. Aren't people using reflection and dynamic in C#? As soon as the code touches such run-time features, the testing at run-time is essential.

I wonder how large projects such as OpenStack, Django, Edx, PyPy deal without static types?


I hate Python. My linux distro comes with version 2.7 yet I should be using version 3?? Yes it makes writing complex programs quickly with its endless libraries, but I don't consider myself learning anything if all I'm doing is copy pasting the API docs. I've recently switched to Go and the language is small and easy, docs/source code are well commented, and lastly I'm actually learning how computer programs work.


Most ppl are trying to solve problems/get work done, not learn how to re-implement functionality already available in libraries. Copy & pasting the API docs lets you focus on solving much harder & more interesting problems.

If you want to learn how computer programs work, you don't have to use existing libraries - you can still implement the functionality yourself.

By your argument (I hate python...it has libraries) any modern & moderately successful language with a large library ecosystem is bad, and you prefer Go precisely because it lacks those libraries?


I'm learning python just to be able to use tensorflow. I wish there was an interface in Ruby


I was a long time Rubyist but switched over to Python because even though its characteristics and philosophy made me reflexively shirk it at first -- particularly significant whitespace, one-line-lambdas, and the clusterfuck of 2.x vs 3.x -- it seemed to me to be an obviously easier language to teach, nevermind its significantly stronger libraries for numerical work.

I'm glad I made that decision. The language was easy enough to pick up in my spare time. I hardly ever use pandas/numpy unless I'm doing some really serious statistical work; the core language and patterns in Python are now pleasant enough for me to use in day-to-day data wrangling and hacking. I'm now mixing in Ruby for a current project -- mostly because I like Rakefiles, and also, Ruby's static site generators like Middleman -- and it's been surprisingly painful to do things in Ruby. I used to hate how when doing a Google search for something in the Python stdlib would bring up 2.x before 3.x...but it almost seems even more problematic in Ruby, where 1.9.3 and 2.0.0 docs keep coming up, even though official maintenance of them has been dropped.

(2.0's maintenance ended in Feb. 2016 http://ruby-doc.org/core-2.0.0/Array.html)

If I didn't know better, I wouldn't even know what Ruby's official version was. For me, Google results show no other documentation for Ruby's Array, as the next results are from tutorialspoint and sitepoint.

And that's not even getting into the issue of how problematic the do-things-how-you-like freedom of Ruby is incredibly hard to discern as an outsider. To give one example I recently had: how do you iterate through a human-calendar-based time interval, such as a month (i.e. any interval that doesn't have a constant length in seconds)?

In Python, I remember how frustrating it was to figure out what the hell the difference was between datetime, time, calendar, the gmtime function, and then timedelta, and then the third-party libraries of pytz and python-dateutil. But once I understood them, which was largely a matter of realizing how naive I was about the nature of measuring time, doing something like iterating over calendar intervals is straightforward.

This is my first Google result for "python iterate month intervals" -- it's from 2008 and still works perfectly: http://stackoverflow.com/questions/153584/how-to-iterate-ove...

Now here's the result for Ruby; all of the answers, as far as I can tell, are not only not-very-Rubyish, but not reliable either: http://stackoverflow.com/questions/1724639/iterate-every-mon...

FWIW, I remember solving this problem by using the DateTimein ActiveSupport. Which is a credit to how much fun and joy it is to build things in Rails right out of the box. But that complexity catches up quick, and including ActiveSupport in day-to-day Ruby work can sometimes to unwanted monkeypatching.


As a Ruby fan who is baffled by Python's continued popularity, I like this comment - I'm always interested to hear why people have such different experiences than me trying to move from the former to the latter.

That said, unless "recently" was years and years ago, Date#next_month is a thing:

  require 'date'
  date = Date.today
  while (date < Date.today.next_year)
    puts date
    date = date.next_month
  end
One thing that I think throws a lot of people is that the official Ruby docs are actually better than Google for figuring stuff like this out - it only takes a couple minutes to find #next_month by perusing the method listing at http://ruby-doc.org/stdlib-2.3.1/libdoc/date/rdoc/Date.html, but do a web search and you get a bunch of Railsy crap.

Though I will grant you that even searches on ruby-doc.org keep bringing up results for Ruby 2.0.x and whatnot. That part is pretty bizarre.


I thought this was a helpful article!


I just wanted to point out a bit of syntax from the article. I'm a huge fan of compact variable declaration if statements. The code from the article:

    if name in names:
        names[name] += 1
    else:
        names[name] = 1
That can actually be written as just one neat, readable line:

    names[name] = names[name] + 1 if name in names else 1
It may not be as readable to some who are used to spelling it out as an if/else block, but I really prefer the one line way. It reads closer to regular English I think.


NO. That is not more readable, and is warned against in most style guides and code-quality books.

In the original, at a glance I know exactly what is going on.

In your version, I have to read the whole sentence carefully to notice that it's even a conditional and not a normal assignment, and then I have to mentally unpack it to understand the logic that you're trying to implement. If/else should never be a one-liner.

Good code is boring code :)


Yup, but the right way to do it would be a defaultdict, or a Counter anyway.

    from collections import defaultdict

    def count_names():
        names = defaultdict(int)
        for name in sys.stdin.readlines():
            name = name.strip()
            names[name] += 1
            ...


Or just `names[name] += 1` if you're using a Counter.


Which would of course be the optimal solution. I always forget about that object.


This is where `collections.defaultdict` shines


My initial progression of languages was: QBasic, Visual Basic, C++, Java (1.5), Python. Python was leaps and bounds more fun and productive than flailing away with any of those.

But today, I'm less excited about it. I've gotten spoiled by C#, that has static typing, and consequently, better tooling, as well as a good measure of the flexibility of Python, through dynamics, lambdas, LINQ.

It seems Python is finally getting over the 2.X -> 3.X schism, but that kind of threw a wrench into things for a number of years, as well.


Is it 2006 again?


[flagged]


Reading the opinions of others gratifies my own intellectual curiosity, and as I am one of HN's readers, it fullfills the definition.

PS: editing your own post to reply is a weird way to do things when there's a "reply" link under each comment...


>Why is a beginner's introduction to one of the common scripting languages at the top of HN?

I think there might be more non-programmers here than you think. Also, those who do program may have friends who don't and they may find the article interesting as something they can refer those friends to.


From the guidelines:

> On-Topic: Anything that good hackers would find interesting. That includes more than hacking and startups. If you had to reduce it to a sentence, the answer might be: anything that gratifies one's intellectual curiosity. [emphasis mine]


Python is very and increasingly popular and I guess the reason it is at the top is to recommend to the people who practice Perl or Ruby to take a look at this language as well.


I've been programming for 20 years and don't know any of those languages.


That's surprising! So which are the languages you use (I'd expect to not know any of them :-))


C++, C#, Javascript and now Swift.

I know many others who have been programming their whole lives in one or two programming languages. Once you get good at something and are well compensated, there may not be enough motivation to learn new languages. Specially when you have kids and other hobbies.


For all its virtues, I feel introductions to Python tiptoe around a very important topic: yes, Python is nice and easy, but you'll have to program the Python way too.

Try running a nested loop on a non-trivial example, and you can end up spending minutes in what would take milliseconds in any other language. If you want to program in Python, you must get used to the functional paradigm. Not "should", "must".

Now, I'm all in for bringing more functional programming into daily life, but I find a bit dishonest that beginners are not told about this. My first serious program took about a week for a task, and shaving that time down involved a lot of pain changing simple nested loops into multiplications of Numpy matrices. There was a lot of caching too. I have no idea how someone without a CS degree would have dealt with this.


> Try running a nested loop on a non-trivial example, and you can end up spending minutes in what would take milliseconds in any other language.

Huh? Can you provide an example? There's nothing about writing nested loops in Python that is qualitatively different from other languages.

> If you want to program in Python, you must get used to the functional paradigm. Not "should", "must".

This is incorrect, much to my chagrin. Python's trend over the past few years has been not only not to encourage functional programming, but to explicitly discourage functional programming. For example, starting in Python 3, `reduce` has been banished from the language proper to the standard library.


Huh? Can you provide an example?

Well he did mention numpy and obviously doing something that can be done in numpy with nested loops will be much much slower. However that is as much a case of numpy being really fast as python being slow.

For example, just tested elementwise multiplication of two 10kX10k matrices and with numpy and numpy arrays it took ~350 ms vs ~15 seconds with a nested for loops and python lists. Still minutes vs. milliseconds seems like extreme hyperbole.

edit: Figured I'd test how long the naive nested loop approach would take in a 'fast' language like Julia, and much to my surprise it took over 50 seconds.

edit2: cleaned up all my code to try to make it as similar as possible across both languages:

Nested for loops python 2.7: ~30 seconds

Nested for loops Julia 4.6; ~50 seconds

Nested for loops PyPy 5.3.1 ~0.9 seconds

Make of these numbers what you will


I've been using Julia a lot lately so these results really surprised me, and I wrote my own test. Punchline: it takes about 0.4 seconds on Julia 0.4.6, on my machine which is several years old. Check it out:

julia> include("elmult.jl")

eachindex

0.42587028

outer loop over rows

8.923323015

outer loop over cols

0.516270241

Code:

    function elmult(m1, m2)
       result = zeros(m1)
       for i in eachindex(m1)
           result[i] = m1[i] * m2[i]
       end
       return result
    end

    function elmult_rowmajor(m1, m2)
        result = zeros(m1)
        nr = size(m1, 1)
        nc = size(m1, 2)
        for i in 1:nr, j in 1:nc
            result[i,j] = m1[i,j] * m2[i,j]
        end
        return result
    end

    function elmult_colmajor(m1, m2)
        result = zeros(m1)
        nr = size(m1, 1)
        nc = size(m1, 2)
        for j in 1:nc, i in 1:nr
            result[i,j] = m1[i,j] * m2[i,j]
        end
        return result
    end

    elmult(rand(3,3), rand(3,3))
    elmult_colmajor(rand(3,3), rand(3,3))
    elmult_rowmajor(rand(3,3), rand(3,3))

    m1, m2 = rand(10000,10000), rand(10000, 10000);

    println("eachindex")
    println(@elapsed elmult(m1, m2))
    println("outer loop over rows")
    println(@elapsed elmult_rowmajor(m1, m2))
    println("outer loop over cols")
    println(@elapsed elmult_colmajor(m1, m2))


Could you post the Julia code? Unfortunately, you do have to make sure that the types are correctly inferred by the compiler in high-performance loops. Or maybe you used a global.

http://docs.julialang.org/en/release-0.4/manual/performance-...


I'll admit I don't really know that much Julia and basically wrote naive MATLAB code (and I wanted to make it as close as possible to my python code):

  s=10000;
  a=ones(s,s);
  b=ones(s,s);
  c=zeros(s,s);

  tic();
  for i in 1:s
    for j in 1:s
      c[i,j]=a[i,j]*b[i,j]
    end
  end
  toc();
Obviously in real code I'd simple write

  c=a.*b 
and get basically the same performance as numpy


Tarrosion is right, on my machine, putting the code inside a function is 10X faster, and then swapping the order of the loops gives another 10X improvement:

    function f(s)
      a=ones(s,s);
      b=ones(s,s);
      c=zeros(s,s);

      tic();
      for j in 1:s
         for i in 1:s
          c[i,j]=a[i,j]*b[i,j]
         end
      end
      toc();
      return c
    end
Note that you also might have to run the function twice, because the first time JIT-compilation kicks in.

Julia 0.5 also now automatically devectorizes some code (eg. x = a .* b .+ c) so that you don't have to write explicit loops to get performance benefits.


Thanks. To both you and Tarrosion.

Guess I need to take some time at some point to sit down and actually learn 'proper' Julia.


It looks like this was done at global scope. It's important to wrap things in a function for maximum performance - AFAIK, because method dispatch and precompilation happen at the function level, functions are much much faster than not functions.

Julia also stores its arrays column major, so put the outer loop over columns for another order of magnitude performance increase. (I'm not sure I love this feature, but presumably there's a reason...maybe for better performance on matrix operations?) My reply to your grandparent comment has a simple implementation that runs in 0.4 seconds on an aging machine.


Based purely on my experience with native CPython, I have usually found for loops to be a bottleneck - and nested list comprehensions to be the saviour.

I wonder what the difference would look like then?


> Can you provide an example?

Gladly. Check the nested loop in [1]. That's exactly what I fought against (although that's not me asking that question). No other language AFAIK suffers from that issue.

[1] http://stackoverflow.com/questions/8097408/why-python-is-so-...


1) That particular example is 10 or 20 seconds on CPython, depending on CPython version, machine, etc.

2) With the exception of Luajit and JS, any dynamic interpreted language will take in the range of 5-20 secs to run equivalent code. I'm pretty sure Ruby and PHP are in the same range, no time to benchmark it now. Besides, if you use the Pythonic version of this loop (using list comprehensions), it will take more like 5 or 10 seconds and not 20. Run the same code on Pypy, and it takes under a second.

3) In any case, if performance is really an issue, the correct answer (as the parent discovered) is to use Numpy or Cython or C extensions for that part of the code. This is not uncommon knowledge.

4) I've been using Python in production for a decade and have never thought of this (~0.2 vs ~10 secs) as a problem because I never used pure Python for critical numeric code (or Ruby, or even JS). I did that in C or Cython, or Numpy (or OCaml, on one occasion). If I had to do something like that now, I'd probably use Rust and call it from Python (assuming I was writing the app in Python).

5) Any language has edge cases like this that can surprise you if you're not familiar with the ecosystem. The higher the level of abstraction, the more edge cases. Look at even the Julia thread directly below this one. It's a massive difference between the naive, Julia beginner version (no offense, I would have written it the same way, probably) and the experienced Julia programmer version. Even a language like Go has performance gotchas.

Python certainly has it's problems (like building large, robust programs, although that's being actively addressed with MyPy types), but I honestly don't agree that this is one of them.


Show me an example that uses `reduce` with a function other than sum/product that makes it clearer than the equivalent loop.


Reduce doesn't have side effects, handles an empty collection, doesn't need to reference the index of the iterable, and self-documents the code as a fold. I find the last part nice because a loop or a Python comprehension would need to add a comment to explain what would otherwise be clear from the syntax.

Here's an alternative example where I think it makes sense (checking if the size of all elements in a collection are equal):

  reduce(lambda a, b: len(a) == len(b), ls)


I don't think that does what you think it does:

  >>> reduce(lambda a, b: len(a) == len(b), ["a", "b", "c"])
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 1, in <lambda>
  TypeError: object of type 'bool' has no len()
It's trying to do len(len("a") == len("b")) == len("c"), which becomes len(True) == len("c"), and len(True) doesn't work.

Some variations which do work are:

  len(set(map(len, ls))) == 1
  len(set(len(x) for x in ls)) == 1
  all(len(ls[0]) == len(x) for x in ls)
  len(min(ls, key=len)) == len(max(ls, key=len))
Append "if ls else True" to handle the empty list.


Ouch, good catch! I can't think of a nice way to salvage reduce but these are some clever alternatives. Point anti-reduce.


This doesn't salvage it in any meaningful sense, but it does work:

  class EqualLengths:
    def __init__(self, size):
      self.size = size
    def __nonzero__(self):
      return True
    def __repr__(self):
      return "True"
  
  def equal_lengths(a, b):
    if isinstance(a, EqualLengths):
      if a.size == len(b):
        return a
      return False
    if a is False:
      return a
    n = len(a)
    if n == len(b):
      return EqualLengths(n)
    return False

  >>> reduce(equal_lengths, ["a", "b", "cc", "d"])
  False
  >>> reduce(equal_lengths, ["a", "b", "c", "d"])
  True
However, I could do something similar with sum():

  class SumEqual:
    def __init__(self):
      self.size = None
      self.is_equal = True
        
    def __add__(self, other):
      if self.is_equal:
        if self.size is None:
          self.size = len(other)
        else:
          self.is_equal = (self.size == len(other))
      return self
      
    def __nonzero__(self):
      return self.is_equal
      
    def __repr__(self):
      return repr(self.is_equal)


  >>> sum(["a", "b", "cc", "d"], SumEqual())
  False
  >>> sum(["a", "b", "c", "d"], SumEqual())
  True
and unlike the first case, this sum() solution will work when there are fewer than two items in the list.


> I don't think that does what you think it does:

Heh, just proved my point. Reduce won't be missed.


Weird, I thought that Python was trying to discourage functional programming with its extremely limited lambdas and the proposal to move map and reduce out of the core language.


The important thing is to fully support first class functions - not the fact that they are anonymous - so I find it difficult to see how the lack of multiline anonymous functions is really a blow to functional Python

I think the argument against map and reduce was that there was better and more Pythonic ways to do both - not because they were 'too functional'.


Kinda. Many things you can do with a map can also be done with a list comprehension or generator, so that seems to be the way to go.

Moving from Scala to Python it was annoying at first.. but honestly the code is easier to read in most cases, so no complaints here.


IIRC, the limitations on lambdas has to do with the way whitespace is parsed rather than being an explicitly conscious decision.


Guido also maintains that by the time you need multiline lambda's, the extra cost of giving the function a name is more than outweighed by the improved readability.

I kinda agree. Certainly it guards against some of the code you see in overly nested javascript.

The downside is that the code is slightly removed from it's call site - but rarely by much.

Overall the increased complexity it would bring to the language has not been justified by anyone arguing for it's benefits. Giving the function a name isn't the worst thing in the world.


Curious what you mean about nested loops? Do you specifically mean nested list comprehensions? If nested they can sometime be less readable than explicit for loops so my advice to a struggling newbie would be "if it hurts stop doing it"

Or did you mean something else?


I don't mean it as "readable", but as in "thanks to type inference, it will take forever". I linked to this question [1] somewhere else, which is something that AFAIK happens only in Python.

[1] http://stackoverflow.com/questions/8097408/why-python-is-so-...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: