7 ms·
PEP 308 and why I still hate Python
- PaulHoule 10y agoWhich language do you like?
- dvt 10y agoI like Java, Javascript, Go (which holds a special place in my heart), and C++ even. And I'm being a bit hyperbolic -- I don't hate Python, but sometimes I feel that the language works against you, and not with you.
- secstate 10y agoNevermind that Javascript has a hideous side too: http://callbackhell.com/ http://callbackhell.com/ And don't get me started with Java's verbosity. Half the time Java seems completely unusable without an auto-completing IDE. And in all honesty I am a big Python fan, but only because it seems like the lesser of all evils in programming. There are some great designs out there, but Python is that toolkit that just seems to be pragmatic enough to be useful and idealistic enough (hello, significant whitespace) to encourage expressive algorithm design.
- djsumdog 10y agoI started taking Scala jobs a while back and I don't think I'd every want to go back to a Java shop. That being said, some things in Scala are difficult to wrap your head around, and anything made by TypeSafe/Lightbend should die in a fire, but overall I still enjoy coding in it.
- deathanatos 10y agoYou like JavaScript, the language where parenthesizing an expression can change the value of that expression[1]: > {} + [] <- 0 > ({} + []) <- "[object Object]" or how the identity x|0 == x doesn't hold for all "integers"[2]: > 4294967296 | 0 <- 0 or how function definitions aren't grammatically statements, making this[3]: function foo() { function bar() {} // legal if(1) { function baz() {} // illegal! } } this just always bites me: > "a string" instanceof String <- false (but seriously, I don't understand why JavaScript needed the object/primitive distinction. I get it for Java, but not in JS.) > sometimes I feel that the language works against you, and not with you. JavaScript is the language where you ask it, "here, I want to know which of these guns most adequately shoots my foot." ES6 improves things considerably; in 10 years we'll have good browser support for basic data structures, like Map and Set. [1]: I'm joking. Read it first, then return to this footnote. The sleight of hand is this: the first expression parses as an empty code block, followed by a unary plus taking an empty list. The second parses as binary addition. There's also a terrible amount of coercion taking place. This also "means" that binary addition "isn't" commutative: {}+[] and []+{} evaluate to different values; the same trickery is involved. [2]: the binary or operator, |, silently converts the operands to a signed 32bit integer for the duration of the expression. Note that signed 32bit integer is a type not available to the JavaScript programmer — it only arises internally! (The only numerical type available is "Number", which is an IEEE double.) [3]: the grammar for functions is essentially "list of statements or function definitions", so function definitions are only valid at the "top level" of a function.
- dvt 10y agoTrue, JS is a pain in the butt. But I think it's fun: it feels fluid and that you can do almost "anything" with it (for better or worse). In Python, I feel that I'm fighting against arbitrary goalposts or that I'm wracking my brain parsing some logical puzzle (like in the PEP example).
- secstate 10y agoProperly spec'd and implemented language structures are the opposite of logical puzzles. JS is not fluid, it's broken.
- BuuQu9hu 10y agoPython has list comprehensions because maths has set comprehensions.
- rbanffy 10y agoReading it as "Alice studies all night if she goes to the library; if not, she'll sleep all night" seems perfectly natural. Having said that, I often use the "else" as a "this should never happen" clause that raises an error.
- dvt 10y agoI agree that it reads naturally, but when dealing with those kinds of sentences, they always need to be put into conditional form (A->B). Even when reading text the order of those words matters. Consider: "I'm going to die ... (gasp) ... if you don't grab me some Subway. I'm starving" The sentence is funny because the apodosis is misleading. Even thought that might be a valid narrative approach when writing a comedy, I don't think it's an appropriate coding one.
- rbanffy 10y ago> The sentence is funny Code should have literary value. ;-)
- stcredzero 10y agoTo be fair, Python isn’t terrible, but throughout its lifetime, it made some incredibly poor design decisions Substitute {{x}} for Python and you have a template for a Hitchhiker's Guide entry for just about every programming language, ever.
- oxryly1 10y agoYup. And Python is certainly one of Stroustrup's two kinds of languages: "There are only two kinds of languages: the ones people complain about and the ones nobody uses." - Bjarne Stroustrup
- ezrast 10y agoI can't think of a language that belongs less in that dichotomy than Python. Programmers used to gush over it like crazy; they only stopped because it became ubiquitous enough that there was no point. Javascript, PHP, and C get an order of magnitude more hate.
- cat199 10y agobut lisp... (occasional lisper)
- oxryly1 10y agoYes lisp. (constant lisper)
- deleted 10y ago[deleted]
- djsumdog 10y agoI agree. The more mature developer understands all languages have their strengths and weaknesses. I really like Python myself, and it's in my top three list of languages I like (Scala, Ruby and Python -- not in any order). Even PHP, which is not a well designed language at all, has at least attempted to make core language improvements in PHP7 and has supersets like Hiphop/Hack which use the same syntax and avoid most of the insane typing pitfalls.
- oxryly1 10y agoWhy didn't Python do this: x = if condition a else b ?
- debacle 10y agoBecause what they actually want is something like: checkSomeValue() && doOtherThing()
- secstate 10y agoBecause that scans as: Variable x should be assigned if condition a true, otherwise b.
- oxryly1 10y agoBut "condition" is just a placeholder. A concrete example would be: msg = if (status == 0) "done" else "error"
- secstate 10y agoTake away the parens (which python is pretty explicit such structure should not be required to be legible). msg = if status == 0 "done" else "error" From a compiler perspective that's a bear to parse.
- scoppini 10y agoI think it could be ambiguous in certain situations. Let's say I wanted to conditionally set a variable to one of two negative constants. In the current syntax, that would look like: x = -1 if y else -2 However, with your syntax, it would look like: x = if y -1 else -2 Which could be possibly confused with trying to subtract 1 from y.
- oxryly1 10y agoAh, and Python uses whitespace and colons to disambiguate, which would ruin the efficiency of this form.
- 10y ago
- tzs 10y agoI'm not sure why the author calls the two branches of in if/else the consequence and the final_consequence. That naming suggests that you do both of them, with the latter coming after the first, which is of course not how an if/else works. I'm sure that nearly everyone reading the article knows how an if/else works, so that naming won't actually lead them astray, but it just feels ugly.
- dvt 10y agoBad wording on my part, point taken.
- ezrast 10y agoAs a fellow member of the hates-Python-but-not-enough-to-quit-my-job-over-it club, comprehensions are just the worst. Uses variables before defining them, can't be readably broken over multiple lines, overloads multiple pieces of syntax, reads inside-to-out instead of left-to-right. Ugh.
- cliffy 10y agoWhat is awful about: foo = [transform(bar) for bar in baz.list() if condition(bar)] ? Seems very readable and expressive. Or are you complaining about how they execute? Also \ used judiciously with proper indentation can break statements over multiple lines without too much pain.
- djsumdog 10y agoYea, I like list comprehensions. I mean they make sense once you're use to reading the syntax. That's just like the following in Scala: foo = baz.list().filter{ bar => condition(bar) }.map(transform(_)).toList If it's your first time looking at Scala, you'd probably be like, "What the fuck is that shit?" but as you learn the language, these types of patterns become common and make a lot of sense. I mean it's not like weird rules in natural language. At least the grammars for computer languages are strict, with very few edge cases (compared to human/spoken language).
- p4lindromica 10y agoI hope you mean: foo = baz.list().filter(condition).map(transform).toList No need to create the extra anonymous functions.
- nerdponx 10y agoDoes Scala have line continuation? I got really used to pipes from R (which I guess come from F#/Elixir), which in turn got me really comfortable with multi-line statements like: foo = baz.\ list().\ filter{ bar => condition(bar) }.\ map(transform(_)).\ toList IMO this is about as readable as it gets. It's like bullet points enumerating each step in the "algorithm" that produces a `foo`. AFAIK Javascript also uses this pattern a lot.
- abecedarius 10y agoA cute feature of this syntax: in "p if c else q" you can think of "if c else" as an infix operator like + and the rest. This operator has an algebra worked out by John McCarthy -- e.g., it's associative. Of course I doubt this will help the poster to like Python more, but it might amuse others.
- derefr 10y agoSo, Ruby has: consequent-expr if antecedent-expr ...which has all the same problems as the PEP308 example, as far as I can tell. Its (implicit) else-clause is just always nil. I can't tell from the author's argument whether this condemns Ruby as well, or if something about the PEP308 style was uniquely bad. I could see something definitely worse about the readability of this code: {long expr} if x else {another long expr} but the author didn't discuss that case.
- Lazare 10y agoThe difference between Ruby and Python here is that Ruby has a perfectly functional ternary operator that works as one would expect. It also allows some other crazy syntax which can be appropriate in some cases, but it doesn't force you to use it in all cases. Python does force you to use their awkward conditional expressions; there is no normal ternary operator. There's a big difference between a language which lets you write hideous code, and a language which forces you to write hideous code.
- TheDong 10y agoPython does not force you to. In any case where you can use PEP 308, you can use a boring traditional "if else".
- jolux 10y agoBut you can't use a normal ternary operator...
- Lazare 10y agoIs that intended as a defense of Python's ability to enable clear, concise, expressive code? :) More seriously: Yes, you are obviously correct. But while you can use if/else, you can't use a ternary, and you can in Ruby. That's why people complain about the lack in Python but don't wrote the same article about Ruby.
- luord 10y ago
- SFJulie 10y agoGvR seems to make readability a priority. But my problem with true if cond else false is it makes impossible to chain fast choices. I thought it was a bug, then I understood it was a feature (after talking to him). GvR hate ternary operators, the python 3nary is midfix, it sux, but it removes the possibility for people to do long chained if/then/else in unreadable ways. If you think I am right and it sux, understand I think forbidding this kind of operator is like hating shortcuts and goto. Since I love shortcuts, goto and chained ift and python, I logically found ways to not care of PEP308 because it is a non problem. Dispatch tables, and/or used wisely ... there are a lot of ways to not care about PEP308.
- dvt 10y ago> GvR seems to make readability a priority. And my point is that going against the standard (for over 100 years) way of reading conditionals is quite the opposite.
- SFJulie 10y agoI do agree, and for me it is ok to disagree with GvR. I would have prefered a ?: but I can replace it with # requires non null default else there is a bug value = arg is MARKER and default or arg So ... I don't bother
- Lazare 10y ago> GvR seems to make readability a priority. I don't find the syntax adopted in PEP 308 to be readable.
- Animats 10y agoPython is an imperative language. The control structure, based on indentation, is well matched to Python's imperative character. Attempts to retrofit a functional style to Python fit Python's syntax badly. Lambdas, conditionals, and list comprehensions look painful if they extend beyond one line, because the indentation assumptions of Python just don't fit. As a practical matter, only use Python's functional features in one-liners.
- nsaslideface 10y agoIndeed. I find the huge "some_method" example pretty much invalid because I'd assign that dict to a variable first, so the line would be a nicer "return my_dict if y else {}". What person, style guide or PEP is forcing anyone to write some_method's return statement? I don't get the ideal of saving space and writing huge one-liners (that in Python you'd have to break up over more lines). As they say on IRC: "if you're worried about using too many lines, I can send you a file full of blank ones."
- userbinator 10y agoPython is an imperative language. ...as are many others with the conditional operator's operands in the normal (condition, true-case, false-case) order: https://en.wikipedia.org/wiki/%3F https://en.wikipedia.org/wiki/%3F: I think being "functional" or otherwise has nothing to do with it. Even in imperative languages you must use expressions, and it is there that the conditional operator is most useful.
- jolux 10y agoYeah, this has nothing to do with FP. No idea what the parent was going for...
- pjvandehaar 10y agohttps://en.wikipedia.org/wiki/%3F%3A https://en.wikipedia.org/wiki/%3F%3A
- Lazare 10y agoYou've identified a real issue (the functional features work badly except as one liners), and a good fix (only use them as one liners). I think the cause has everything to do with some poor choices around the parser and syntax, however, and nothing to do with its imperative nature as such.
- joshbaptiste 10y agoI rarely see PEP 308 in code bases
- gorthol 10y agoI've been doing Python professionally for 13 years (among other languages, but Python is in the one I've used more). I like the language but I also hate some things (mainly, the GIL, the lack of static typing now lessened thanks to mypy and the slowness), but I never tough of the ternary if as evil or found a single instance where it confused me.