1. 10
  1.  

  2. 2

    Always good to see someone diving into the interpreter internals, but man I find supporting -‘ incomplete ternary expression to be a weirdly uncomfortable motivation for doing so.

    1. 3

      It is a complete expression, else defaults to None and you can’t return from your weirdly comfortable ternary expression whereas you can conditionally return from a function with postfix if which btw is a one-liner.

      1. 1

        It is a complete expression

        Didn’t say it wasn’t; I said it was an incomplete ternary expression, which is definitionally true.

        else defaults to None

        Understood, but not obviously a compelling syntactical feature and, if you ever decide to take up typing discipline, an antipattern in the making.

        and you can’t return from your weirdly comfortable ternary expression whereas you can conditionally return from a function with postfix if which btw is a one-liner

        Also not exactly a compelling feature, and returning from within an expression is ambiguous in a statement based language:

         value = return 42 if True
        

        Is that valid syntax? Is value dead code? Or can it only ever be None if reachable?

        Besides, you can already conditionally return in one line, so not sure that ability adds anything:

        if True: return 42
        

        I’m not some huge fan of Python’s ternary conditional, having picked up TCL’s terser version first, but shoe-horning TCL style syntax would also be an odd motivator for forking my own personal Python, with all the distribution problems that brings.

        1. 1

          Return with a bottle of wine if you can. I want wine conditionally and you want my statement to be as readable as possible. So it is obviously not an anti-pattern.

          value = return 42 if True
          
          # Is that valid syntax? Is value dead code? Or can it only ever be None if reachable?
          

          It would be invalid syntax. rhs can’t be a void value. Are we just making up uses where syntax might be confusing or harder to read? Is that the point?

          value = if True: return 42  
          

          This would probably throw the same error if if expressions could be used as rhs. Unfortunately they cannot be and it is an error. Another missing feature. The syntax is miserable, but yes, it is a one-liner.

          1. 1

            Return with a bottle of wine if you can. I want wine conditionally and you want my statement to be as readable as possible. So it is obviously not an anti-pattern.

            The statement:

            return bottle if wine else None
            

            … is arguably more readable than:

             return bottle if wine
            

            … if only because what is returned is explicit in all cases. Both are an antipattern when you’re being disciplined on types, because you’ve got one expression that evaluates to more than one possible type.

            Are we just making up uses where syntax might be confusing or harder to read? Is that the point?

            No attempt at straw manning, I’m actually uncertain of what valid syntax is for return in this two-thirds-of-ternary form. That uncertainty comes from its inherent instability, does:

            return bottle if wine
            print(“foo”)
            

            Return either bottle or None, terminating the function and making the print unreachable, or does control flow continue past that line of wine is False?

            return bottle if wine else None
            print(“foo”)
            

            Notice how there’s no question here that the print is unreachable.

            Unfortunately they cannot be and it is an error.

            The ternary if form — the only form of if expression in Python — can be used as the RHS of a return. The language just requires that such an expression must unambiguously evaluate to either the LHS or the RHS of the “if predicate” portion. Trying to return an if statement is nonsensical and should error.

            Another missing feature. The syntax is miserable, but yes, it is a one-liner.

            I see no missing feature. All I see is a bit of syntactic sugar that seems to have no obvious positives — without more clearly understanding the valid uses of return-if it certainly looks like it’s just the ternary if with “else None” elided — but which very clearly conflicts with two of the maxims of the Zen of Python (one obvious way to do things and explicit is better than implicit). As for the syntax being “miserable”… well that’s how I feel about Ruby, generally, so not sure we’ll come to any meaningful conclusions on that particular unprovable value judgement.

            1. 1

              I think the confusion lies where you missed the second half of the post where postfix if makes the return conditional. Else None makes it completely different. It will return None if condition is not met. This is not what it does. Yes, “finding syntax useful” is subjective, but it exists, and it is used, so it is useful. And it will lose its use when people stop using it. That’s the pragmatic solution to your philosophical dilemma. And you can have Optional[int] as the return type in python, so I don’t understand your protests of having anti-patterns and type inconsistencies. That’s where python does better I think. And that’s why I use it instead of ruby.

              1. 1

                I think the confusion lies where you missed the second half of the post where postfix if makes the return conditional. Else None makes it completely different. It will return None if condition is not met. This is not what it does.

                No, I didn’t miss the second half of the post, what I’m saying is that the Ruby-style syntax is inherently ambiguous, and that using the nil case to bypass return is semantically weird, logically inconsistent, and confusing to learners, all in one go.

                In Python the semantics of;

                var = EXPR
                return var
                raise RuntimeError()
                

                … are unambiguous; we always return whatever EXPR evaluates to, and in all cases control flow ceases and any code below the return statement is unreachable. I can glance at this and know that error is never raised.

                More importantly those first lines contracted into one one always has precisely the same behavior (modulo incrementing and decrementing a reference counter):

                return EXPR
                raise RuntimeError()
                

                But in Ruby-style syntax that’s not the case:

                var = EXPR
                return var
                raise RuntimeError()
                

                … can never throw that error, while:

                return EXPR
                raise RuntimeError()
                

                might do so, because EXPR may include a conditional.

                Besides, there already exists an obvious way to do this motivating example:

                def foo(test):
                     a = 1
                     return a if test
                     a += 1
                     return a
                

                … without considering early return at all:

                def foo(test):
                     a = 1
                     if test:
                         a += 1
                     return a
                

                Yes, “finding syntax useful” is subjective, but it exists, and it is used, so it is useful. And it will lose its use when people stop using it.

                Ahh, but it doesn’t exist in Python, and the present debate is over whether or not it makes sense to go to the trouble of adding an ambiguous and inconsistent feature to the language when, again, the addition essentially duplicates and mildly bikesheds functionality that has already been provided in an unambiguous and consistent way. Personally I’m all for this useful thing losing its use, but I’m sure it shouldn’t be added to the language in a misguided attempt to increase its use.

                That’s the pragmatic solution to your philosophical dilemma.

                I haven’t got a dilemma, and arguably the most pragmatic solution is to use the idioms of a language as you find them, rather than trying to shoehorn in idioms lifted from other languages, especially when those foreign idioms already have native solutions that are perfectly workable.

                1. 1

                  I think this is a pointless argument for inconsistency and shoehorning full of your personal preferences using counterexamples since you can do it for any language where the same keyword is used for two different idioms.

                  1. 1

                    Think what you’d like, but if you’re not ready to address concerns such those as I’ve raised you’ll never get your personal preference for this new idiom adopted into Python. Of course you’re welcome to incorporate it into your own personal Mython, though I’m not sure the distribution pain is worth it. But hey, you choose what hill to die on.

                    1. 1

                      You think I’d go to lengths to get my idea implemented and that your “arguments” provide some sort of basis for validity? Illusions of grandeur? It’s inconsistent because I don’t expect it. It’s an anti-pattern because I don’t know what Optional means. Languages don’t need new features because you can use existing syntax. Clicking reply on lobste.rs or any forum is not the kind of actual I would take if I wanted to get this implemented. I would go implement it, come up with a couple of actual useful real life examples, write a PEP and send a diff.

                      1. 1

                        I would go implement it, come up with a couple of actual useful real life examples, write a PEP and send a diff.

                        Please do. Then watch it be rejected for all the reasons listed above.

                        The phrase is “delusions of grandeur”, BTW.

                        1. 1

                          Great, thanks for your time.