conditional expressions - add parens?

Now that we have started to see conditional expressions ... I would like to see them parenthesized. The parens aren't as important as they are with generator expressions, but ... they matter.
From a recent checkin --
level = 0 if "absolute_import" in self.futures else -1 Mentally, I can't help parsing that as "level = 0" plus comments that turn out to be code that triggers backracking. When the expressions (particularly the true case) are longer, it gets even worse. I think that adding parentheses would help, by at least signalling that the logic is longer than just the next (single) expression. level = (0 if "absolute_import" in self.futures else -1) -jJ

On 3/6/06, Jim Jewett <jimjjewett@gmail.com> wrote:
I'm not sure, are you suggesting the grammar/parser enforces it that way, or that it should be in PEP-8? (I still can't help but go 'yecchh' whenever I see the code. It looks like Perl's 'expr if expr' form, but it behaves quite different. Right now, removing if/else expressions still looks like the best solution, to me :-> But gauging reactions (my own and others) to the actual if-expr in use is the main reason I added those couple of lines to the compiler package.) -- Thomas Wouters <thomas@python.org> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

On 3/6/06, Thomas Wouters <thomas@python.org> wrote:
On 3/6/06, Jim Jewett <jimjjewett@gmail.com> wrote:
level = 0 if "absolute_import" in self.futures else -1
I think that adding parentheses would help ...
level = (0 if "absolute_import" in self.futures else -1)
I'm not sure, are you suggesting the grammar/parser enforces it that way, or that it should be in PEP-8?
I would prefer that the grammar enforce it, but putting it in PEP 8 would be a half-way measure. I can't imagine an expression small enough that the parentheses really hurt. var = t if c else f var = (t if c else f) In PEP 8, I would even go so far as to recommend parentheses around the three sub-expressions if they contain any internal whitespace, but I don't think the grammar should enforce that.
Yah, that sounds uncontroversial. :D -jJ

Jim Jewett wrote:
Personally I think the above code exemplifies exactly why Guido was correct in his reluctance to add conditional expressions.
Contrast with the bleeding obvious: level = 0 if "absolute_import" in self.futures: level = -1 or even, if a certain obscurity is desirable: level = - ("absolute_import" in self.futures) regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

Morel Xavier wrote:
Sure, and for those uses it's good enough. This isn't really a python-dev topic, though, so I'll avoid following up further on this list. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

Morel Xavier wrote:
And of course the example I criticized was a list comprehension (not). The fact that ternary operators improve some features isn't an excuse for using them when they actually decrease readability. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

"Steve Holden" <steve@holdenweb.com> wrote in message news:440CAAFB.5060702@holdenweb.com...
Wait a second. I may be just a user but if the above is correct then that syntax needs to die! There is no logical reason for "XX if YY else ZZ" to be roughly equivlent to: "if (YY) then {ZZ} else {XX}" , but AFAICT that is pretty much the way you expanded that. I hope I misunderstood, or that there was a typo in a post.

[Jim Jewett]
[Steve Holden]
In honor of Peter Naur receiving the 2005 Turing Award: <http://campus.acm.org/public/pressroom/press_releases/3_2006/turing_3_01_200...> and remembering Python's Algol roots, I'd like to constrast it with the truly obvious: level = (if "absolute_import" in self.futures then 0 else -1) That way also has the minor advantage of computing the same value for `level` as Jim's code ;-) [Joe Smith]
Ya, Steve just got it backwards. "(X if Y else Z)" is the same as "(if Y then X else Z)", except for the excessive novelty. The obvious spelling would require making "then" a keyword, which is actually OK with everyone :-)
I hope I misunderstood, or that there was a typo in a post.
You were lucky this time, bucko, but don't ever go questioning a python-dev regular again ;-)

Alex Martelli wrote:
but which parens ? level = 0 if "absolute_import" in self.futures else -1 level = 0 if ("absolute_import" in self.futures) else -1 level = (0 if "absolute_import" in self.futures else -1) level = (0 if ("absolute_import" in self.futures) else -1) level = ((0) if ("absolute_import" in self.futures) else (-1)) # ... if you're asking me, I'd say that the second alternative is most readable here. at least as long as level = if ("absolute_import" in self.futures) then 0 else -1 is not on the list... level = 0 or -1 depending on "absolute_import" in self.futures </F>

On 3/6/06, Alex Martelli <aleaxit@gmail.com> wrote:
Recent language features seem to be suffereing from excessive parenthesisitis. I worry that people will stop remembering which expressions requirement parens in which context. Perhaps the solution is to require parens around all expressions, a simple consistent rule. If so, then adding parens around all statements is a fairly natural extension, which solves a number of problems like how to make a richer lambda. Jeremy

On 3/7/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:
Agreed. Mandatory parentheses purely for readability are ultimately futile - I bet I can write unreadable code even if the parens were required :-))))))))))))))))))))))))) The parentheses around genexps were (AFAICT) different - without them, the grammar was ambiguous, so some way of disambiguating was needed. +0 for mentioning parens around conditional expressions in PEP 8. But it's aready covered by the general "code should be readable" in my view. Paul.

Paul Moore wrote:
Agreed - and often the best way to make a conditional expression readable is to not use it in the first place, which is a concept that an official policy on parentheses may mask. And then there's the question of how to parenthesise chained conditional expressions. Mandatory parentheses in that case would make me wonder if I was writing a certain language that isn't Python. . . Given that the main reason PEP 308 was finally implemented was to provide OOWTDI for conditional expressions (instead of the handful of not-at-all-obvious and not-quite-right-either workarounds that had developed in their absence), I expect to see of rush of enthusiastic overuse of the new expression, which will eventually settle down as everyone remembers that not every problem is a nail to be hit with the shiny new hammer ;) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org

On 3/7/06, Paul Moore <p.f.moore@gmail.com> wrote:
The out-of-order evaluation is a very large change, because now we have a situation where normal parsing completes an expression, but needs to avoid evaluating it, just in case. Currently, we can write: >>> if False: >>> print r >>> else: >>> print 6 6 >>> r Traceback (most recent call last): File "<pyshell#14>", line 1, in -toplevel- r NameError: name 'r' is not defined In the above example, r doesn't get evaluated because the if ahead of it says to skip that branch. But with conditional expressions, that flow control is changed from *later* in the program. I don't think we'll see the equivalent of Intercal Suck Points anywhere but intentionally obfuscated code, but I do expect to see: >>> side_effect() if condition In fact, I think the below examples are reasonable uses that do a better job of expressing intent than the if statement would. I just don't like the mental backtrack they require, and would like some sort of advance warning. Parentheses at least tell me "You're not done yet; keep reading." >>> ack(r,r) if r not in cache >>> log(message) if error_flag -jJ

Jim Jewett wrote:
I think you've misunderstood the nature of the change. HTe new conditionals are *expressions*, they aren't postfix conditionals for statements. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

On Mar 7, 2006, at 7:29 AM, Steve Holden wrote: ...
Right, but the only effect of that on the examples is that they both need an 'else None' continuation or thereabouts. I also predict widespread over-use of the new toy and agree with Jim that mandatory parentheses around the whole (X if Y else Z) construct would ameliorate legibility a bit. Alex

Paul Moore wrote:
Indeed. Writing readable code is ultimately the responsibility of the person doing the writing. It's enough that you *can* put parentheses around things if it helps readability. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiam! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+

Jeremy Hylton wrote:
Perhaps the solution is to require parens around all expressions, a simple consistent rule.
I actually designed a language with that feature once. It was an exercise in minimality, with hardly anything built-in -- all the arithmetic operators, etc. were defined in the language. A result was that there was no built-in notion of precedence, and my solution was to require parentheses around every infix operation. So instead of dsq = b * b - 4 * a * c you would have had to write dsq = ((b * b) - ((4 * a) * c)) I never got an implementation working well enough to find out how much of a disaster this would have been to use, though. :-) -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiam! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+

"Greg Ewing" <greg.ewing@canterbury.ac.nz> wrote in message news:440E2614.8050508@canterbury.ac.nz...
Well the original was almost certainly a tongue-in-cheek reference to LISP. LISP was a disaster to use, so I doubt your language would have been any worse. The way one identifies a lisp programmer is to find the person whose paren keys have worn competely off their keyboard. :D

On 3/11/06, Joe Smith <unknown_kev_cat@hotmail.com> wrote:
Given how much Python is indebted to Lisp, digs at Lisp seem particularly off-topic for this list. Fully expecting this to bounce, -- --Guido van Rossum (home page: http://www.python.org/~guido/)

Joe Smith wrote:
LISP was a disaster to use, so I doubt your language would have been any worse.
At least Lisp would let you say (* 4 a c) and not force you to write (* (* 4 a) c) My language would not have been so forgiving, unless you were willing to define a bunch of different * functions with different numbers of parameters. BTW, I did use Lisp and Scheme fairly heavily for a period, and didn't find them to be disasters -- at least not because of the parens. Greg

With parentheses, we can use "if cond then val1 else val2" form without the burden of hacking the parser, although the cost of the keyword "then" is still there. so, some possible forms that prompts in my mind are level = (if "absolute_import" in self.future then 0 else -1) level = (if "absolute_import" in self.future: 0 else: -1) level = (0 if "absolute_import" in self.future else -1) -Jiwon On 3/7/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:

On 3/6/06, Jim Jewett <jimjjewett@gmail.com> wrote:
I'm not sure, are you suggesting the grammar/parser enforces it that way, or that it should be in PEP-8? (I still can't help but go 'yecchh' whenever I see the code. It looks like Perl's 'expr if expr' form, but it behaves quite different. Right now, removing if/else expressions still looks like the best solution, to me :-> But gauging reactions (my own and others) to the actual if-expr in use is the main reason I added those couple of lines to the compiler package.) -- Thomas Wouters <thomas@python.org> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

On 3/6/06, Thomas Wouters <thomas@python.org> wrote:
On 3/6/06, Jim Jewett <jimjjewett@gmail.com> wrote:
level = 0 if "absolute_import" in self.futures else -1
I think that adding parentheses would help ...
level = (0 if "absolute_import" in self.futures else -1)
I'm not sure, are you suggesting the grammar/parser enforces it that way, or that it should be in PEP-8?
I would prefer that the grammar enforce it, but putting it in PEP 8 would be a half-way measure. I can't imagine an expression small enough that the parentheses really hurt. var = t if c else f var = (t if c else f) In PEP 8, I would even go so far as to recommend parentheses around the three sub-expressions if they contain any internal whitespace, but I don't think the grammar should enforce that.
Yah, that sounds uncontroversial. :D -jJ

Jim Jewett wrote:
Personally I think the above code exemplifies exactly why Guido was correct in his reluctance to add conditional expressions.
Contrast with the bleeding obvious: level = 0 if "absolute_import" in self.futures: level = -1 or even, if a certain obscurity is desirable: level = - ("absolute_import" in self.futures) regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

Morel Xavier wrote:
Sure, and for those uses it's good enough. This isn't really a python-dev topic, though, so I'll avoid following up further on this list. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

Morel Xavier wrote:
And of course the example I criticized was a list comprehension (not). The fact that ternary operators improve some features isn't an excuse for using them when they actually decrease readability. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

"Steve Holden" <steve@holdenweb.com> wrote in message news:440CAAFB.5060702@holdenweb.com...
Wait a second. I may be just a user but if the above is correct then that syntax needs to die! There is no logical reason for "XX if YY else ZZ" to be roughly equivlent to: "if (YY) then {ZZ} else {XX}" , but AFAICT that is pretty much the way you expanded that. I hope I misunderstood, or that there was a typo in a post.

[Jim Jewett]
[Steve Holden]
In honor of Peter Naur receiving the 2005 Turing Award: <http://campus.acm.org/public/pressroom/press_releases/3_2006/turing_3_01_200...> and remembering Python's Algol roots, I'd like to constrast it with the truly obvious: level = (if "absolute_import" in self.futures then 0 else -1) That way also has the minor advantage of computing the same value for `level` as Jim's code ;-) [Joe Smith]
Ya, Steve just got it backwards. "(X if Y else Z)" is the same as "(if Y then X else Z)", except for the excessive novelty. The obvious spelling would require making "then" a keyword, which is actually OK with everyone :-)
I hope I misunderstood, or that there was a typo in a post.
You were lucky this time, bucko, but don't ever go questioning a python-dev regular again ;-)

Alex Martelli wrote:
but which parens ? level = 0 if "absolute_import" in self.futures else -1 level = 0 if ("absolute_import" in self.futures) else -1 level = (0 if "absolute_import" in self.futures else -1) level = (0 if ("absolute_import" in self.futures) else -1) level = ((0) if ("absolute_import" in self.futures) else (-1)) # ... if you're asking me, I'd say that the second alternative is most readable here. at least as long as level = if ("absolute_import" in self.futures) then 0 else -1 is not on the list... level = 0 or -1 depending on "absolute_import" in self.futures </F>

On 3/6/06, Alex Martelli <aleaxit@gmail.com> wrote:
Recent language features seem to be suffereing from excessive parenthesisitis. I worry that people will stop remembering which expressions requirement parens in which context. Perhaps the solution is to require parens around all expressions, a simple consistent rule. If so, then adding parens around all statements is a fairly natural extension, which solves a number of problems like how to make a richer lambda. Jeremy

On 3/7/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:
Agreed. Mandatory parentheses purely for readability are ultimately futile - I bet I can write unreadable code even if the parens were required :-))))))))))))))))))))))))) The parentheses around genexps were (AFAICT) different - without them, the grammar was ambiguous, so some way of disambiguating was needed. +0 for mentioning parens around conditional expressions in PEP 8. But it's aready covered by the general "code should be readable" in my view. Paul.

Paul Moore wrote:
Agreed - and often the best way to make a conditional expression readable is to not use it in the first place, which is a concept that an official policy on parentheses may mask. And then there's the question of how to parenthesise chained conditional expressions. Mandatory parentheses in that case would make me wonder if I was writing a certain language that isn't Python. . . Given that the main reason PEP 308 was finally implemented was to provide OOWTDI for conditional expressions (instead of the handful of not-at-all-obvious and not-quite-right-either workarounds that had developed in their absence), I expect to see of rush of enthusiastic overuse of the new expression, which will eventually settle down as everyone remembers that not every problem is a nail to be hit with the shiny new hammer ;) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org

On 3/7/06, Paul Moore <p.f.moore@gmail.com> wrote:
The out-of-order evaluation is a very large change, because now we have a situation where normal parsing completes an expression, but needs to avoid evaluating it, just in case. Currently, we can write: >>> if False: >>> print r >>> else: >>> print 6 6 >>> r Traceback (most recent call last): File "<pyshell#14>", line 1, in -toplevel- r NameError: name 'r' is not defined In the above example, r doesn't get evaluated because the if ahead of it says to skip that branch. But with conditional expressions, that flow control is changed from *later* in the program. I don't think we'll see the equivalent of Intercal Suck Points anywhere but intentionally obfuscated code, but I do expect to see: >>> side_effect() if condition In fact, I think the below examples are reasonable uses that do a better job of expressing intent than the if statement would. I just don't like the mental backtrack they require, and would like some sort of advance warning. Parentheses at least tell me "You're not done yet; keep reading." >>> ack(r,r) if r not in cache >>> log(message) if error_flag -jJ

Jim Jewett wrote:
I think you've misunderstood the nature of the change. HTe new conditionals are *expressions*, they aren't postfix conditionals for statements. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd www.holdenweb.com Love me, love my blog holdenweb.blogspot.com

On Mar 7, 2006, at 7:29 AM, Steve Holden wrote: ...
Right, but the only effect of that on the examples is that they both need an 'else None' continuation or thereabouts. I also predict widespread over-use of the new toy and agree with Jim that mandatory parentheses around the whole (X if Y else Z) construct would ameliorate legibility a bit. Alex

Paul Moore wrote:
Indeed. Writing readable code is ultimately the responsibility of the person doing the writing. It's enough that you *can* put parentheses around things if it helps readability. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiam! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+

Jeremy Hylton wrote:
Perhaps the solution is to require parens around all expressions, a simple consistent rule.
I actually designed a language with that feature once. It was an exercise in minimality, with hardly anything built-in -- all the arithmetic operators, etc. were defined in the language. A result was that there was no built-in notion of precedence, and my solution was to require parentheses around every infix operation. So instead of dsq = b * b - 4 * a * c you would have had to write dsq = ((b * b) - ((4 * a) * c)) I never got an implementation working well enough to find out how much of a disaster this would have been to use, though. :-) -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiam! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing@canterbury.ac.nz +--------------------------------------+

"Greg Ewing" <greg.ewing@canterbury.ac.nz> wrote in message news:440E2614.8050508@canterbury.ac.nz...
Well the original was almost certainly a tongue-in-cheek reference to LISP. LISP was a disaster to use, so I doubt your language would have been any worse. The way one identifies a lisp programmer is to find the person whose paren keys have worn competely off their keyboard. :D

On 3/11/06, Joe Smith <unknown_kev_cat@hotmail.com> wrote:
Given how much Python is indebted to Lisp, digs at Lisp seem particularly off-topic for this list. Fully expecting this to bounce, -- --Guido van Rossum (home page: http://www.python.org/~guido/)

Joe Smith wrote:
LISP was a disaster to use, so I doubt your language would have been any worse.
At least Lisp would let you say (* 4 a c) and not force you to write (* (* 4 a) c) My language would not have been so forgiving, unless you were willing to define a bunch of different * functions with different numbers of parameters. BTW, I did use Lisp and Scheme fairly heavily for a period, and didn't find them to be disasters -- at least not because of the parens. Greg

With parentheses, we can use "if cond then val1 else val2" form without the burden of hacking the parser, although the cost of the keyword "then" is still there. so, some possible forms that prompts in my mind are level = (if "absolute_import" in self.future then 0 else -1) level = (if "absolute_import" in self.future: 0 else: -1) level = (0 if "absolute_import" in self.future else -1) -Jiwon On 3/7/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:
participants (14)
-
Alex Martelli
-
Fredrik Lundh
-
Greg Ewing
-
Guido van Rossum
-
Jeremy Hylton
-
Jim Jewett
-
Jiwon Seo
-
Joe Smith
-
Morel Xavier
-
Nick Coghlan
-
Paul Moore
-
Steve Holden
-
Thomas Wouters
-
Tim Peters