On Wed, 2008-09-10 at 20:55 +0100, Arnaud Delobelle wrote:
[Sorry for the private reply earlier]
On 10 Sep 2008, at 19:43, Cliff Wells wrote:
Greetings,
Something that has started to annoy me in the last couple of years is the fact that most Python control statements cannot be used as expressions. I feel this is a pretty deep limitation and personally I don't feel it's well-justified.
As I understand it, the reason for the distinction mostly has to do with the premise "flat is better than nested", which I can understand, but I don't think carries enough weight anymore.
Specifically, I'd like to see things like "if" statements, "for" loops, etc, become expressions. This would not preclude them from being used as if they were statements (an expression can stand alone on a line of Python code), but would add a lot of expressiveness to the language as well as make Python more viable for creating DSLs.
Can you post some sample code to illustrate how statements could be used as expressions?
Do you propose that we write:
y = if x == 0: 0 else: exp(x**-2)
instead of:
y = 0 if x == 0 else exp(x**-2)
Yes, and parentheses could be used to disambiguate, as anywhere else.
? Or, how would you write
factors = [x for x in range(2, n) if n % x == 0]
? Something like this maybe:
factors = for x in range(2, n): if n % x == 0: x
Or do you suggest something else?
These are correct, albeit simple examples (you are using only assignment examples). To give something more interesting, I'd like to be able to do things like this: dispatch = { '1': lambda x: ( for i in range(x): if not x % 2: yield 0 else: yield 1 ), '2': lambda x: ( for i in range(x): yield i ) } for i in dispatch[val](1): print i Note that this isn't just about lambda, but rather general expressiveness. To clarify, I propose *not* making syntax changes that add to the language or alter the meaning of existing code. Rather my proposal is along the lines of "relax this particular syntax requirement" and let the chips fall where they may. In other words, Python 2.x code would still work, it simply would not take advantage of a particular coding style now available to it. The key difference between a statement and an expression is that 1) an expression has a return value, a statement does not 2) statements cannot be used inside of expressions In short, statements are more-or-less castrated expressions. They have no other special features.
Additionally, removing statements from Python would also allow the language to be simplified. No need for a ternary "if" operator with different semantics than a normal "if" statement, "for" loops would be brought closer to generators in functionality, and the perceived limitations of lambda would disappear, amongst other things. We'd gain a lot of features found in languages like Lisp and Ruby as a side- effect (i.e. anonymous code blocks).
Overall it seems this design decision is specifically geared toward forcing programmers into an imperative style in order to enforce program readability. In Python 1.5, this made a bit of sense, but as Python has "matured" (or in my view, gotten over-complicated) this makes much less sense. Many parts of Python's extensive syntax are explicit workarounds to this design decision. So on the one hand we have the perceived danger that programmers will write nested code and on the other we have an ever-expanding syntax. I'd take the former any day.
So do you think readability is not as important now as it was?
Of course not. I'm saying that due to this limitation, readability is going down the drain even faster. It's getting to the point where it's not possible to keep the whole of Python in your head and I feel that a significant portion of this is due to this particular inflexibility. Further, I feel that this limitation forces programmers into using hacks and magic or overly spread-out code, which itself leads to readability concerns. Having used Python for around a decade, I'm quite aware of the fact that you can happily write tons and tons of nice code with Python in its current state. However, because of the direction of my work (developing a internal DSL in Python) I've suddenly become aware of this glass ceiling. I'd bumped into it before back when I was doing a lot of GUI development, but blamed it on lambda rather than realizing that it wasn't lambda so much as what I am bringing up now.
I've not delved into the internals of the Python interpreter to check, but I suspect that converting most statements to expressions would not be very difficult (changing the grammar definition and generated bytecode a small amount in most cases).
Any thoughts on this? I'm sure it's been brought up before, but I haven't found any definitive discussions on why this rather arbitrary design decision continues to hold in the face of a general migration away from imperative languages (especially when it seems it could be changed without much backwards-compatibility issues).
I think to call this feature of Python an arbitrary design decision is a misjudgement. To me it is central to the identity of Python.
Sorry, I misspoke: it's not an arbitrary *decision*, but it is an arbitrary *distinction*. As I said, I'm aware of why this decision was originally made (prevention of nested code, a.k.a. fear of lisp), but the distinction itself is completely artificial, created to enforce a model of programming, rather than for technical or performance reasons. I agree that it is a distinguishing feature of Python, but I don't think it is central to Python's identity. That is, it wouldn't be "not Python" were it removed. Regards, Cliff