Introduce and-if and or-if operators

Just adding a link to the Wikipedia section, which if I understand is what OP is partly describing, and a relevant quote (includes the code snippet):

if (expressionA && myfunc(b)) {
    do_something();
}

if myfunc(b) is supposed to perform some required operation regardless of whether do_something() is executed, such as allocating system resources, and expressionA evaluates as false, then myfunc(b) will not execute, which could cause problems. Some programming languages, such as Java, have two operators, one that employs minimal evaluation and one that does not, to avoid this problem.

Last sentence may be a good place to look at @MRAB. I’m no expert to explain it though.

Very interesting article regardless.

yes. just as we have an alternative to lead pipes in the modern day. despite lead pipes “working” for so long.

What they are asking is for a syntax that emphasizes that and lazily evaluates its arguments, a syntax that highlights that it is equivalent to a nesting of if.

There is no change to formal logic.

2 Likes

Right now, if statements have nothing to do with lazy evaluation. if expects a single Boolean value, and makes flow control decisions based on that.

and is lazy whether or not it is used in producing the Boolean value for an if statement.

# Evaluates to None, printing "ignored" as a side effect
>>> 3 and print("ignored")
ignored

# Evaluates to 0, without calling print at all.
>>> 0 and print("ignored")
0

New syntax would just make things less clear. Not only do you need to learn the form, but you need to think about whether if a and b: and if a and if b: are different, and if not, why is there a separate form in the first place? And no, we’re never going to remove the ability to write if a and b:.

5 Likes

I disagree with this. Lazy evaluation is extremely useful when subsequent conditions are dependent on the first:

if isinstance(x, SomeClass) and x.some_method_on_class(): ...

Trying to write this without lazy expressions would necessitate nesting, and Python prefers to avoid unnecessary nesting.

I also disagree with the suggestions to use | for “or” (since no reader would know why you were doing that without a comment), and the block-melding idea. If you want eager evaluation of something, just do it explicitly:

result = dependent_condition()  # Evaluate this unconditionally.
if primary_condition() or result: ...

In my experience, this pattern comes up very rarely since most conditions don’t have side effects.

8 Likes

If you want the functions to be called for a effect, you should call them, and then after calling both, condition on the result.

if x() and y():
    ...
else:
    # no guarantee y was called

vs

x_result, y_result = x(), y()
if x_result and y_result:
    ...
else:
    ....

I don’t see adding syntax to avoid short circuiting as either generally useful or necessary, and having multiple ways to do this rather uncommon thing isn’t needed.

6 Likes

if a and b: is parsed as if (a and b):, where a and b is a specific example of an expression. People should learn and be taught to see it this way. The keyword if is not part of the expression and should not be mixed into it. This is one place where reading the doc entry is really needed for those without experience with similar contructs in other languages.

12 Likes

having two ways to do the thing with subtle differences is good because then it’s pretty obvious that they do subtly different things.

but we don’t have an eager equivalent of and/or. (no, bitwise arithmetic on int doesn’t count: True & 4 vs True and 4)

since most conditions don’t have side-effects, what’s wrong with making eager the default?

alternatively you have fun coming up with syntax and a reasoning for eager eval.

(in some languages it’d make sense to have and? and and!, python is not one of them. and if is our suggestion for lazy eval (with plain and being eager), the reasoning is that if is a statement and statements are only executed when the program reaches the relevant line of code/statement, while expressions are generally assumed to execute all at once - aside from the wrench lazy and throws into the assumption. thus the if part of and if only runs if it reaches the second condition in the and. which is easier to explain. this reasoning is why the proposal would work, while we can’t think of a similarly good reasoning to explain what an eager eval is.)

You’ve been given a perfectly good way to do it. Assign both (or all) the parts of the condition to variables, THEN combine them. This is the simplest and most obvious way to enforce a particular evaluation order.

You’re asking for the language to fit itself to your brain. Aside from being remarkably arrogant, that’s not really going to work, because your brain is unique and Python has to work for everyone, not just you. Have you considered working with the language instead of fighting against it?

2 Likes

Eager is not going to become the default in Python because it has never been the default in Python, and it’s not just about side-effects because you might be protecting against exceptions such as can happen with subscripting or division.

Or

if all([x(), y()])
    ...

Does it? Or are all the people it didn’t trip up simply not posting about it?

3 Likes

Addressing the above:

Soni: this isn’t going to happen. Short circuit boolean logic has been baked into programming culture since at least 1968. There is not and never has been a one to one correspondence between computer and natural languages,

Others: No, Python x and y does not necessarily correspond with the ambiguous English x and y,. The Carpenters went to #2 on the Billboard chart in 1971 with “Rainy Days and Mondays” getting them down: from context, that includes sunny Mondays and wet Tuesdays. While it’s unreasonable to change the computer language, it’s not unreasonable to understand and be sympathetic to the concern.

And let’s stop with scare quote we’s and similar snark.

1 Like

you should double-check our arguments. none of them are about natural language. you might be confusing with everyone else’s counterarguments.

rather, they’re purely technical: expressions should not be lazy, statements should be lazy.

This is your opinion, but it’s not something language designers agree with.

All the most-popular programming languages have short-circuiting logical operators: C, C++, JavaScript, Java, Python, Ruby, PHP, Haskell, Rust, Go, C#, Swift, etc. It’s hard to find languages in wide use that don’t have them.

9 Likes

thankfully, language designers are human too.

which means they can be wrong.

(and yes, it is possible for a vast majority of ppl to be consistently wrong about something. it happens fairly often, especially in politics, but there’s no reason it can’t happen in other areas as well.)

You are never going to convince people to change Python in a backward-incompatible way by insisting that a common pattern among languages is wrong. You should drop this.

13 Likes

Ned is right. This is never going to happen in Python. Further discussion here is a waste of time and good will.