Abstract and concrete syntax

D

David Baelde

Hi,

I tried python, and do like it. Easy to learn and read (at least for the
commonly used part), has a very large community so great doc and
contributions, and... the design is clean. I come from functional
programming languages, and I do like the proper static binding, the first
class functions. That's what interests me in Python. It's the most modern
of those addictive scripting languages.

But, there is something I can't believe. Statements are not expressions. I
tried to find some doc about that on the web. I'm not satisfied, and I'd
like to learn more and discuss here.

First, there are some trolls about Python Zen forbidding statements to be
expressions. But I think the Zen is often contradictory. I don't like
trolls, want something serious.

Basically, I found one good point against statements-as-expressions: it
cannot fit the indentation sensitive syntax.

---
http://mail.python.org/pipermail/python-list/2005-January/260566.html
Python allows statements inside suites and suites inside compound
statements. It also allows expressions inside statements and expressions
inside expressions. The one thing it never ever does is allow a suite or a
statement inside an expression, because doing so would utterly destroy the
handling of significant white space.
---

I feel there are some real problems here. But I can't find anything
absolutely unsolvable. I played a few examples, can't get anything
ambiguous. Maybe the nesting analyzer
(http://python.org/doc/2.4.1/ref/indentation.html) needs to take into
account parenthesis-like delimiters together with indentation, but that
doesn't look impossible (although I suspect it's harder than I can imagine).
The parenthesis trick could avoid over-deep indentation.

set_callback(obj,
lambda x: (if a:
2
else:
3)

Well, I suspect there are some moral issues, and maybe pythonists don't
want statements in expressions. PEP #308 was about having a ternary (?:)
operator for expression level conditional, pythonists rejected it. I'd
like to read more about the motivations of the vote.

Many people will tell me that my tiny example can be written with the
if-else outside the assignation. I claim it's better to be able to express
it the way you mean it. That's why lambda is here for, too.

More generally, I think there is no abstract distinction between
statements and expressions. Everything is an expression, can be evaluated
to a value. Making function first class objects was the same kind of good
and beautiful idea. So if there is no abstract distinction, why should
there be a concrete one? If it's just a technical issue, let's work on it.

But I guess you'll have more to say on that subject...
__
David
 
J

John Roth

David Baelde said:
Hi,

I tried python, and do like it. Easy to learn and read (at least for the
commonly used part), has a very large community so great doc and
contributions, and... the design is clean. I come from functional
programming languages, and I do like the proper static binding, the first
class functions. That's what interests me in Python. It's the most modern
of those addictive scripting languages.

But, there is something I can't believe. Statements are not expressions. I
tried to find some doc about that on the web. I'm not satisfied, and I'd
like to learn more and discuss here.

First, there are some trolls about Python Zen forbidding statements to be
expressions. But I think the Zen is often contradictory. I don't like
trolls, want something serious.

Basically, I found one good point against statements-as-expressions: it
cannot fit the indentation sensitive syntax.

---
http://mail.python.org/pipermail/python-list/2005-January/260566.html
Python allows statements inside suites and suites inside compound
statements. It also allows expressions inside statements and expressions
inside expressions. The one thing it never ever does is allow a suite or a
statement inside an expression, because doing so would utterly destroy the
handling of significant white space.
---

I feel there are some real problems here. But I can't find anything
absolutely unsolvable. I played a few examples, can't get anything
ambiguous. Maybe the nesting analyzer
(http://python.org/doc/2.4.1/ref/indentation.html) needs to take into
account parenthesis-like delimiters together with indentation, but that
doesn't look impossible (although I suspect it's harder than I can
imagine).
The parenthesis trick could avoid over-deep indentation.

set_callback(obj,
lambda x: (if a:
2
else:
3)

Well, I suspect there are some moral issues, and maybe pythonists don't
want statements in expressions.

There are a number of ways of doing it; I suspect that the BDFL
simply doesn't want it.
PEP #308 was about having a ternary (?:)
operator for expression level conditional, pythonists rejected it. I'd
like to read more about the motivations of the vote.

Well, Guido has been against it from the start. He finally decided to
put it up to the community to vote on the appropriate syntax. As you
can imagine, there were a huge (well, a couple of dozen) different
syntax suggestions, so it was effectively impossible to get a majority
vote. Result: proposal killed permanently with a sham showing of
giving the community a say in it.

Unfortunately, I found out about Condorcet voting too late; by that
time the original tallies no longer existed so they could not be
reanalyzed.
 
G

Greg Ewing

David said:
Statements are not expressions.

I feel there are some real problems here. But I can't find anything
absolutely unsolvable.

There's no doubt that these problems could be solved in
a technical sense, but the real issue is whether the
resulting code would be *readable*. One of Python's
major strengths is that its code is usually very easy
to read, even if it means being a bit more verbose at
times than strictly necessary.

All the proposals I've seen for statements-in-expressions
in Python (and there have been quite a few) have been a
disaster in the readability department
PEP #308 was about having a ternary (?:)
operator for expression level conditional, pythonists rejected it.

Actually, it was really Guido who rejected it, because
Pythonistas failed to reach a consensus on syntax, and he
wasn't really hot on the idea in the first place. If he
had really wanted it, he would have just picked a syntax
himself.
More generally, I think there is no abstract distinction between
statements and expressions. Everything is an expression, can be evaluated
to a value.

That's true in a functional language, but Python is not a
functional language. In imperative programming, often you just
do something for its side effect, and there's no obvious value
to return. Forcing everything to return a value just for the
sake of conceptual purity is an artificiality, in my view.
 
G

George Sakkis

Greg Ewing said:
That's true in a functional language, but Python is not a
functional language. In imperative programming, often you just
do something for its side effect, and there's no obvious value
to return. Forcing everything to return a value just for the
sake of conceptual purity is an artificiality, in my view.

Well, I guess what makes an artificiality is subjective then, because
IMO the distinction between expressions and statements is a bigger
artificiality. Python already uses a default value (None) to return
from a callable, so what makes statements special ? Certainly not the
side effects, as the two equivalent ways to set an attribute show:
a.x = val # statement
setattr(a,'x',val) # expression

George
 
M

Michele Simionato

From a purist perspective the distinction
statements/expressions is a mistake.
However, if your primary concerns is readability,
it makes sense, since it enforces ifs, try.. excepts, etc.
to be consistently written for all coders. This definitely
helps code review.

Michele Simionato
 
D

David Baelde

Well, thanks for the answers. I guess the fact is that python does not
want to be a functional programming language. This concept is quite large,
and since there is a proper notion of function with closure, I'd say
python is already quite a functional programming language. Even if
assignations and side effects are used all the time (which makes python
easier to learn than a stricter functional programming language in my
opinion).

I agree that statements as expressions could allow obscure code. But it's
so more beautiful concept, makes things simpler to understand! Moreover,
doing this would have kept backward compatibility.

Anyway, I guess it's dead.
The design of programming languages is a complicated thing...
__
David
 
A

Andrea Griffini

I tried python, and do like it. Easy to learn and read

This is a key point. How easy is to *read* is considered
more important than how easy is to *write*.

Re-read the absence of a ternary operator or the limitations
of lambda in python under this light (about lambdas note
that you can define a named function in a local scope if
you need it; and those are full-blown functions and not
just a single expression).

HTH
Andrea
 
T

Terry Reedy

David Baelde said:
Well, thanks for the answers. I guess the fact is that python does not
want to be a functional programming language.

Correct. Python is a procedural, functional, OO language.
I agree that statements as expressions could allow obscure code.

Guido considered (and, I presume, still considers) the distinction between
statement and expression to be a feature, not a wart. Most Python
functions do things that in Lisp require 'special forms' (or builtin
macros, or whatever, in a particular version) with special quoting rules.

For instance, if assignment were done in an expression, the targets would
have to be quoted to avoid having them evaluated. Or the assignment
expression would have to be a 'special expression' that did not evaluate
all its terms (like setq in some (just older?) lisps). In Python, that
'special expression', with its 'quote, don't evaluate, targets' rule, is a
statement!
The design of programming languages is a complicated thing...

To make everything hang together, yes.


Terry J. Reedy
 
M

Mandus

As someone who like to do functional style programming, but without a
lot of training in that dept., I miss what you ask for from time to
time.

I don't want to go to much into this discussion, just comment on a tiny
little bit:

Thu, 09 Jun 2005 03:32:12 +0200 skrev David Baelde:
[snip]
set_callback(obj,
lambda x: (if a:
2
else:
3)
[snip]

You can do stuff like this: lambda x: x and 2 or 3

Of course, you are still quite limited in what you can do, but it have
solved some of my problems...

mvh,
 
K

Kay Schluehr

Mandus said:
As someone who like to do functional style programming, but without a
lot of training in that dept., I miss what you ask for from time to
time.

I don't want to go to much into this discussion, just comment on a tiny
little bit:

Thu, 09 Jun 2005 03:32:12 +0200 skrev David Baelde:
[snip]
set_callback(obj,
lambda x: (if a:
2
else:
3)
[snip]

You can do stuff like this: lambda x: x and 2 or 3

You can also do this

lambda x: {True:2,False:3}.get(bool(a))

which is both beautiful and pythonic.

Kay
 
G

George Sakkis

Mandus said:
Thu, 09 Jun 2005 03:32:12 +0200 skrev David Baelde:
[snip]
set_callback(obj,
lambda x: (if a:
2
else:
3)
[snip]

You can do stuff like this: lambda x: x and 2 or 3

Of course, you are still quite limited in what you can do, but it have
solved some of my problems...

Another case I've found handy to use lambdas and expressions instead of
named functions and statements is for simple properties:

class SomeArray(object):
dimensions = property(
fget = lambda self: (self.x,self.y),
fset = lambda self,(x,y): setattr(self,'x',x) or
setattr(self,'y',y))

Again, it is quite limited, but properties are also often limited so
it's a useful idiom to know.

George
 
G

George Sakkis

Kay Schluehr said:
Thu, 09 Jun 2005 03:32:12 +0200 skrev David Baelde:
[snip]
set_callback(obj,
lambda x: (if a:
2
else:
3)
[snip]

You can do stuff like this: lambda x: x and 2 or 3

You can also do this

lambda x: {True:2,False:3}.get(bool(a))

which is both beautiful and pythonic.

Kay

Beauty and 'pythonicity' are in the eye of the beholder; IMO both are
much less obvious than the if/then/else, especially for a beginner or
someone who has never seen these idioms before. I personally don't find
the (ab)use of dictionaries in this case to be more beautiful or
pythonic than the and/or idiom (not to mention the runtime cost of
building a new dictionary every time), but YMMV.

George
 
G

George Sakkis

Kay Schluehr said:
You can also do this

lambda x: {True:2,False:3}.get(bool(a))

which is both beautiful and pythonic.

Kay

Beauty is in the eye of the beholder, and the same holds for
'pythonicity'; IMO both are much less obvious than the if/then/else,
especially for a beginner or someone who has never seen these idioms
before. I personally don't find the (ab)use of dictionaries in this
case to be more beautiful or pythonic than the and/or idiom (not to
mention the runtime cost of building a new dictionary every time), but
YMMV.

George
 
T

Terry Reedy

This is limited by the requirement (often met) that bool(true-branch) ==
True
You can also do this

lambda x: {True:2,False:3}.get(bool(a))

This is limited by the requirement that both branches be computable
regardless of the value of the condition.
which is both beautiful and pythonic.

Beauty is in the eye of the beholder. It seems that relative pythonicity
sometimes is also ;-).

Terry J. Reedy
 
B

Benji York

George said:
Another case I've found handy to use lambdas and expressions instead of
named functions and statements is for simple properties:

class SomeArray(object):
dimensions = property(
fget = lambda self: (self.x,self.y),
fset = lambda self,(x,y): setattr(self,'x',x) or
setattr(self,'y',y))

How about:

class SomeArray(object):
@apply
def dimensions():
def fget(self):
return (self.x, self.y)
def fset(self, (x, y)):
self.x = x
self.y = y
return property(fget, fset)

It doesn't have the "one-liner" appeal of the lambda version, but it
reads well.
 
D

David Baelde

For instance, if assignment were done in an expression, the targets would
have to be quoted to avoid having them evaluated. Or the assignment
expression would have to be a 'special expression' that did not evaluate
all its terms (like setq in some (just older?) lisps). In Python, that
'special expression', with its 'quote, don't evaluate, targets' rule, is a
statement!

That's not such a big issue, many languages solve that without quoting.
Ruby, for example. I agree that there's a point here. But nothing to do
with quoting.

You refer to Lisp, here's how things work in Caml: standard variables
cannot be assigned, only defined with [let x = v in ...]. But you can
create references, which can be assigned. When you wanna get the value of
a ref you use [!x], if you wanna set it, use [x := ...]. It allows you to
write [(if test then x else y) := ...], which is actually rarely needed.
Thus, making implicit the ! everywhere except before := is acceptable. And
you get the usual behavior with python. Finally, you just have to choose
the value of [x = v], maybe [v], maybe [None].

__
David
 
D

David Baelde

lambda x: {True:2,False:3}.get(bool(a))

I also think these solutions are just hacks, less efficient, less
readable. One shouldn't have to twist her mind to write such an easy idea.
__
David
 
K

Kay Schluehr

Terry said:
This is limited by the requirement that both branches be computable
regardless of the value of the condition.


Beauty is in the eye of the beholder. It seems that relative pythonicity
sometimes is also ;-).

That's what is really regrettable! Otherwise a creation of a "lazy
dict" that creates the value part of an item on demand would have been
reasonable to solve both the computational issue you mentioned and the
performance issue George worried about ( you are both right except for
the little example above :)

Kay
 
R

Robert Kern

Terry said:
Beauty is in the eye of the beholder. It seems that relative pythonicity
sometimes is also ;-).

Ah, the curse of Pythonicity Relativism! What has society come to that
it cannot recognize Absolute Pythonicness and Absolute Perlishness? The
measure of Pythonicness was given to us in the inerrant Gospel of Tim!
Every word of it is literally True! Incant the words "import this" and
you shall see in glowing letters before you the Gospel of Tim. Count the
number of verses For and the number Against. If the For verses outnumber
the Against, the construct is Pythonic, absolutely and without
equivocation for all people as Guido indented.

ask-me-how-to-calculate-the-age-of-the-universe-ly y'rs,
Acolyte Kern

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
D

David Baelde

You can do stuff like this: lambda x: x and 2 or 3
And by the way, I just noticed that this kind of hack is essentially
"pushing the control (statement) inside expressions"... People should
really admit that statements are expressions and stop twist their mind.

I sure can write unreadable python without statement-as-expressions, and
this is an example of it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top