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


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.


* * * * * 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:


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."


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:
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:
  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.


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):
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):
        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.


[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>



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))?


I guess is that.

Collection library has:



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:


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:

  import time
It'll take 5 seconds to crash with a "NameError: name 'fdafadsfadsf' is not defined". Likewise, if you do this:

  import time
  x = 1
  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.


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)?

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