Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

PEP 308 and why I still hate Python

$
0
0

I’m not a python guy, but it seems that every job I’ve had has slowly pushed me into doing more and more Python until I end up doing nothing but Python all day. And I hate doing Python all day.

To be fair, Python isn’t terrible, but throughout its lifetime, it made some incredibly poor design decisions. One such decision, and the subject of this blog post, is PEP 308 ― Conditional Expressions .

A conditional primer

Before we dive into Python, let’s first look at the nature of the conditional; first, in grammar, and then, in logic. In English (a natural language), we often say things like:

$$\text{If Alice goes to the library, she studies all night.}$$

Linguists split up this sentence into the condition, known as the protasis ― and the consequence, called the apodosis :

$$\overset{Protasis}{\overbrace{\text{If Bob goes to the party}}}\text{, }\underset{Apodosis}{\underbrace{\text{he will fail the test}}}\text{.}$$

Note that in ordinary speaking or writing, the consequence doesn’t always follow the condition. Consider:

$$\underset{Apodosis}{\underbrace{\text{Bob will pass the test}}}\text{ }\overset{Protasis}{\overbrace{\text{if he studies with Alice}}}\text{.}$$

But in logic, a symbolic language meant to represent (among another things) natural language, it does. In fact, in every major symbolic system (except for Frege’s idiosyncratic and two-dimensional Begriffsschrift , published 1879), the consequence, known as the consequent , comes after the condition, known as the antecedent :

$$\begin{array}{ccc}

\text{Russel & Whitehead (1910)} & \text{ukasiewicz (1924)} & \text{Modern}\\

A\supset B & \text{C}AB & A\rightarrow B

\end{array}$$

The semantics are unchanged, so we can informally symbolize the above sentences like so (I do some pronoun substitution to make them less ambiguous):

$$\overset{Antecedent}{\overbrace{\text{Alice goes to the library}}}\rightarrow \underset{Consequent}{\underbrace{\text{Alice studies all night}}}$$

or, in the reversed case:

$$\overset{Antecedent}{\overbrace{\text{Bob studies with Alice}}}\rightarrow \underset{Consequent}{\underbrace{\text{Bob will pass the test}}}$$

This small example hopefully shows how a consistent formalism like a very bare-bones logic can make seemingly different linguistic constructs take the same shape. In other words, we now have the tools to turn all kinds of sentences into \(A\rightarrow B\) format. How cool is that!

Programming languages as formal systems

It shouldn’t come as much of a surprise that most programming languages take full advantage of these kinds of logical formalisms. In our case, we see if-then-else statements follow the same structure:

if(condition()) { consequence() } else { final_consequence() }

Logically, we can symbolize this as follows:

\(condition()\rightarrow consequence()\) \(\neg condition()\rightarrow final\_consequence()\)

where \(\neg\) is the symbol for logical negation. We can also handle if-then-elif-else blocks like this one:

if(P()) { Q() } else if (R()){ S() } else if (T()) { U() } else { Z() } \(P()\rightarrow Q()\) \((\neg P()\wedge R())\rightarrow S()\) \((\neg P()\wedge \neg R()\wedge T())\rightarrow U()\) \((\neg P()\wedge\neg R()\wedge\neg T())\rightarrow Z()\)

where \(\wedge\) is the symbol for logical conjunction (read as and ). My examples all use C-style syntax, but many languages use this basic structure. For example Ruby:

if x > 2 puts "x is greater than 2" elsif x <= 2 and x!=0 puts "x is 1" else puts "I can't guess the number" end

Or Lisp:

(if (> 4 5); if-part (message "4 falsely greater than 5!") ; then-part (message "4 is not greater than 5!")); else-part

And even the Erlang people do it:

if some_condition -> some_code; some_other_condition -> some_other_code; true -> else_code end.

Due to some implementation details, true -> acts as the “catch all” else but is generally avoided, per the (official?) Erlang tutorial :

else or true branches should be “avoided” altogether: ifs are usually easier to read when you cover all logical ends rather than relying on a “catch all” clause.

In fact, according to Richard O’Keefe :

It may be more FAMILIAR, but that doesn’t mean else is a good thing. I know that writing ; true -> is a very easy way to get else in Erlang, but we have a couple of decades of psychology-of-programming results to show that it’s a bad idea. I have started to replace:

if X > Y -> a() if X > Y -> a()
; true -> b() ; X =< Y -> b()
end end
by
if X > Y -> a() if X > Y -> a()
; X < Y -> b() ; X < Y -> b()
; true -> c() ; X == Y -> c()
end end

which I find mildly annoying when writing the code but enormously helpful when reading it.

Is else evil?

Although you might find some that disagree , else is not really all that bad. In fact, if we define “evil” as the degree of logical complexity, your else clause is only slightly more evil than your last elif clause ― the else clause negates all branches, as opposed to elif which negates all branches, save one:

$$\begin{array}{cc}

\hfill\text{elif:} & (\neg A\wedge\neg B\wedge C)\rightarrow Z\\

\hfill\text{else:} & (\neg A\wedge\neg B\wedge{\color{red}\neg C)\rightarrow Z}

\end{array}$$

So if our argument is “ else is evil,” it ought to extend to elif as well. I don’t think that’s a concession many would be okay with. Furthermore, else is sometimes downright necessary. Programmers are a lazy bunch, and at some point they all agreed that they would no longer want to write code like this:

var x; if (condition()) { x = A(); else { x = B(); }

Instead, it would be great to write something like:

var x = condition() ? A() : B();

And so, the conditional expression (also known as the ternary operator ? : ) was born. Even though the syntax changed, the order of the operands (condition, A, B) and the semantics are unchanged:

$$\mathbb{\mathtt{x\:=\:condition()\:?\:A()\::\:B()}\equiv}\begin{cases}

condition()\rightarrow A()\\

\neg condition()\rightarrow B()

\

Viewing all articles
Browse latest Browse all 9596

Trending Articles