[Python-ideas] Syntax: 'return: ...' expressions

Andrew Barnert abarnert at yahoo.com
Sat Jan 24 07:06:53 CET 2015


On Friday, January 23, 2015 2:06 PM, Ron Adam <ron3200 at gmail.com> wrote:

> > 
> 
> On 01/23/2015 08:56 AM, Nick Coghlan wrote:
>>  On 21 January 2015 at 11:16, Guido van Rossum<guido at python.org>  
> wrote:
>>>  >So it's hard to say to what extent this was a conscious choice 
> and to what
>>>  >extent it was just tradition. But there's nothing necessarily 
> wrong with
>>>  >tradition (up to a point). I think it still makes sense that 
> statements are
>>>  >laid out vertically while expressions are laid out horizontally. 
> Come to
>>>  >think of it, mathematics uses a similar convention -- a formula is 
> laid out
>>>  >(primarily) horizontally, while a sequence of formulas (like a 
> proof or a
>>>  >set of axioms) is laid out vertically.
> 
>>  I really like that "each statement is like a single step in a
>>  mathematical proof" analogy.
> 
> I agree.
> 
> 
> There are some other distinctions.  When you consider these, you can see 
> how many language designers come to similar solutions.
> 
> 
> Expressions evaluate in unique name spaces, while statements generally do 
> not. Consider "a + b"; it is evaluated in a private method after the 
> values 
> a and b are passed to it.

I don't think that's true. Consider "a[b] = c", which is a statement, but it's evaluated in a private method after the values a, b, and c are passed to it. The fact that it's a.__setitem__ rather than a.__add__ doesn't seem particularly important. I think the key is that __setitem__ doesn't have a return value--like (nearly) everything in Python that mutates state--and therefore there's no expression for it. The question is, what does that buy?

> Statements are used to mutate the current name space, while expressions 
> generally do not.

This is closer. I think, more generally, statements are used to mutate the important state that the local function is all about mutating. And the thing that gets mutated is almost always the leftmost thing. That definitely helps in scannability.

> Statements can alter control flow, while expressions generally do not.

Sure, but I think this part only really helps if control flow is somehow visible. In Python, it is, because control flow almost always means compound statements, which means indentation, and very little else means indentation.

> Having a clear distinction between expressions and statements makes reading 
> and understanding code much easier.

Definitely. That's the part I think is key, but am struggling to explain.

I think Guido offers a great analogy in mathematical proofs, but the question is to find the actual commonality behind the analogy.

After some more thought on this, I think what it comes down to is that (idiomatically-written) Python lets you skim the control flow (because all non-trivial control flow, and very little else, is expressed in terms of indentation) and the state transitions (because each statement generally mutates at most one thing, and it's the leftmost thing), so you can quickly find the part of the code you actually need to read carefully, instead of having to read the whole thing.

I've written this idea up in a bit more detail here:

http://stupidpythonideas.blogspot.com/2015/01/statements-and-expressions.html


> I believe Python follows most of these conventions in most places, and when 
> it doesn't, it's usually for a practical reason that are fairly obvious.
> 
> For example, an "or" expression is a bit of both.
> 
> Another example of how python chooses a practical alternative is we can 
> nest expressions instead of using "call" statements on separate lines 
> and a 
> stack to hold the augments and return values.  That is what python does in 
> the byte code so we don't have to do it in explicit statements.
> 
> If you factor out all expressions you get byte code.  Or if you factor out 
> all statements you get something like lisp.

I don't think either part of that is true. Bytecode is full of things that are expressions—even your paradigm case of an operator expression is handled by an opcode. And conversely, CoffeeScript (if you avoid break/continue/return statements) factors out all statements, and Ruby comes close to doing so, and yet they're really not more Lisp-like than Python in any meaningful way.

> Of course this subject is definitely a very subjective one which relays on 
> agreeing on the general meaning of the above sentences.  OR... YMMV.


More information about the Python-ideas mailing list