Statements as expressions [was Re: Undefined behaviour in C]
Steven D'Aprano
steve at pearwood.info
Tue Mar 29 20:05:51 EDT 2016
On Tue, 29 Mar 2016 10:31 pm, BartC wrote:
> On 29/03/2016 09:26, Steven D'Aprano wrote:
>> On Monday 28 March 2016 12:40, Paul Rubin wrote:
>
>
>> The point is that there's nothing intrinsically obvious or right about
>> "return the value of the last statement in the block".
>
> But that's exactly what happens inside a typical function: you have
> linear sequence of statements, then you a have return statement: at the
> end. It's a common pattern.
But return is an *explicit* exit. And not all languages work that way.
{My Pascal syntax may be a bit rusty...}
function demo(int x): int;
begin
demo := x + 1; {sets the return value}
writeln('x has the value', x);
writeln('returning now...');
end;
[...]
>> An expression naturally and intrinsically should return the value the
>> expression calculates. This is such a no-brainer that I feel stupid even
>> writing it: "x+1" should return "x+1". It would be crazy to pick
>> something else.
>
> (This is in contradiction to what you say elsewhere, where:
>
> graph + node
>
> may be procedural.)
Not at all. With operator overloading, the plus operator + ends up as a
method call __add__ or __radd__. This method call can have side-effects,
and it can return anything it likes, including None. That return value can
be ignored, but it is still the return value of the expression:
graph + node # returns None, use this expression for the side-effects only
Just like print(a, b, c) returns None, and we use if for the side-effects.
It's still an expression ("call the print function with these arguments"),
it does something (prints) and then returns None.
>> But a statement is a statement because it doesn't have a return value.
>
> Isn't an expression technically a statement in Python?
I mean statements which are not legal expressions, like:
del x
import module
from module import name
for x in seq: block
while condition: block
try ... except ... else ... finally
etc. I'm sorry that I wasn't pedantic enough to specify "statements (apart
from expressions)" each time I contrasted statements and expressions. Can
you possibly forgive me for my informal use of language?
> Therefore a
> statement could have a value. But take this example:
>
> if cond1: x=a1
> elif cond2: x=a2
> elif cond3: x=a3
> else: x=a4
>
> Clearly this would be better expressed as (not valid Python):
>
> x = if cond1: a1
> elif cond2: a2
> elif cond3: a3
> else: a4
x = a1 if cond1 else a2 if cond2 else a3 if cond3 else a4
We can split it over multiple lines too:
x = (
a1 if cond1 else
a2 if cond2 else
a3 if cond3 else
a4
)
> (Actually 'del is a rather odd language feature. And I can't figure out
> how it's implemented; how does it manage 'del x[i]'? Anyway that's
> another matter.)
del x[i] calls x.__delitem__(i)
>> True if that allowed the value to be garbage
>> collected, False if it wasn't? Or the other way around? None of these
>> suggests feel either useful or obviously right.
>
> It doesn't need to give a useful value.
Hence my suggestion that all statements (apart from expressions) return 42.
> Its 'value' lies in being able to have it in a sequence or block:
>
> z = del x; y
In a hypothetical Python where `del x` returns None, that would set z to
None and then evaluate y, doing nothing with the result.
--
Steven
More information about the Python-list
mailing list