[Python-ideas] `if-unless` expressions in Python

Chris Angelico rosuav at gmail.com
Mon Jun 3 21:24:00 EDT 2019


On Tue, Jun 4, 2019 at 10:58 AM James Lu <jamtlu at gmail.com> wrote:
>
> `if-unless` expressions in Python
>
>     if condition1 expr unless condition2
>
> is an expression that roughly reduces to
>
>     expr if condition1 and not condition2 else EMPTY
>
> This definition means that expr is only evaluated if `condition1 and not condition2` evaluates to true. It also means `not condition2` is only evaluated if `condition1` is true.

Why the double condition? The existing definition of "condition1 and
not condition2" already guarantees the short-circuiting, and what
you're effectively creating is two pieces of a single condition.

> # EMPTY
>
> EMPTY is not actually a real Python value-- it's a value that collapses into nothing when used inside a statement expression:
>
>     print([
>       if False never_called() unless False,
>       if False never_called() unless False,
>     ]) # => []
>
>     print([
>       3,
>       if False never_called() unless False,
>       if False never_called() unless False,
>       2,
>       if True 5 unless False,
>       4
>     ]) # => [3, 2, 5, 4]
>
>
> EMPTY is neither a constant exposed to the Python runtime nor a symbol. It's a compiler-internal value.

Okay, now this starts to look somewhat interesting. But what you'd be
creating here would be a feature of specific language constructs, and
probably wouldn't work everywhere.

> # Use cases
>
> Assertions.
>
>     assert if condition1 predicate(object) unless condition2
>
> (This would be more readable with assert expressions.)

Honestly not sure what this does that's better than ordinary
expressions. Can you give some concrete examples of how you would use
this, and what the equivalent code for current Pythons would look
like?

> Macros.
>
> # Equivalent syntax in existing Python
>
> As a statement:
>
> if condition1 and not condition2: predicate(object)
>
> predicate(object) if condition1 and not condition2

Adding "else None" would make this legal Python syntax right now, but
for very good reasons, is not how most people write code.

So, looking just at the "EMPTY" part. Allow me to reword your proposal
into what I think you're saying; is this what you're proposing?

## New "unless" construct for list displays and argument lists ##

Inside a list/dict/set/tuple display, or inside an argument list,
elements can be conditionally omitted by providing a predicate.

lst = [f1(), f3() unless f2(), f4()]

The functions will be called in the order indicated. If f2() returns a
falsey value, f3() will not be evaluated, and the list will have only
two elements in it.

#####

That's without the two-part condition. You can always put "expr unless
x and not y" if you need both parts.

How close is this to what you were thinking of?

ChrisA


More information about the Python-ideas mailing list