Minor gripe: The ability to *articulate* Python is not the same as the
ability to *type Python verbally*.
Nobody articulates `def area(width, height): return width * height` as *def
area, open paren, width, comma, space, height, closed paren..*.
They would say something like *def area as a function of width and height,
equal to width by height*.
-- Carl Smith
carl.input@gmail.com
On 12 May 2018 at 18:24, Steven D'Aprano
On Sat, May 12, 2018 at 08:16:07AM -0700, Neil Girdhar wrote:
I love given compared with := mainly because
Simpler is better than complex: * given breaks a complex statement into two simpler ones,
(Foreshadowing: this argument applies to augmented assignment. See below.)
I don't see how you justify that statement about "given". I think that it is "given" which is more complex. Significantly so.
Let's compare the syntax:
target := expr
That is a single, simple expression with a single side-effect: it assigns the value to <target>. That's it.
Like all expressions, it returns a value, namely the result of "expr". Like all expressions, you can embed it in other expressions (possibly wrapping it in parens to avoid precedence issues), or not, as required.
(That surrounding expression can be as simple or complex as you like.)
Now here's Nick's syntax:
target given target = expr
Exactly like the := version above, we can say that this is a single expression with a single side-effect. Like all expressions, it returns a value, namely the result of "expr", and like all expressions, you can embed it in other expressions.
So far the two are precisely the same. There is no difference in the complexity, because they are exactly the same except for the redundant and verbose "given" spelling.
But actually, I lied.
Nick's syntax is *much more complicated* than the := syntax. Any arbitrary expression can appear on the left of "given". It need not even involve the binding target! So to make a fair comparison, I ought to compare:
target := expr
which evaluates a single expression, binds it, and returns it, to:
another_expr given target := expr
which evaluates "expr", binds it to "target", evaluates a SECOND unrelated expression, and returns that.
If you want to argue that this is more useful, then fine, say so. But to say that it is *simpler* makes no sense to me.
Option 1: evaluate and bind a single expression
Option 2: exactly the same as Option 1, and then evaluate a second expression
How do you justify that Option 2 "given", which does everything := does PLUS MORE, is simpler than Option 1?
That's not a rhetorical question.
which is putting people off in the simple examples shown here (some people are annoyed by the extra characters). However, when given is used in a list comprehension to prevent having to re-express it as a for loop, then two simple statements are easier to understand than one complex statement.
I'd like to see an example of one of these list comprehensions that is simpler written with given. Here's an earlier example, an exponentially weighted running average:
average = 0 smooth_signal = [(average := (1-decay)*average + decay*x) for x in signal] assert average == smooth_signal[-1]
I'm not even sure if "given" will support this. Nick is arguing strongly that bound targets should be local to the comprehension, and so I think you can't even write this example at all with Nick's scoping rule.
But let's assume that the scoping rule is the same as the above. In that case, I make it:
average = 0 smooth_signal = [average given average = (1-decay)*average + decay*x) for x in signal]
Is it longer, requiring more typing? Absolutely.
Does it contain a redundantly repetitious duplication of the repeated target name? Certainly.
But is it simpler? I don't think so.
If you don't like the exponential running average, here's a simple running total:
total = 0 running_totals = [total := total + x for x in xs]
versus
total = 0 running_totals = [total given total = total + x for x in xs]
If you don't like this example either, please show me an example of an actual list comp that given makes simpler.
This is a common difference between code written at programming contests versus code written by those same software engineers years later at big companies. Code that you write for yourself can be compact because you already understand it, but code you write professionally is read many many more times than it is written. Accessibility is much more important than concision.
Ah, nice rhetorical argument: "given" is for professionals, := is a hack for amateurs and programming contests. Seriously?
Do you use augmented assignment? Your simple versus complex argument for "given" applies well to augmented assignment.
Augmented assignment combines two conceptual operations:
x = x + 1 - addition (for example) - assignment
into a single operator:
x += 1
By your argument, augmented assignment is more complex, and we ought to prefer splitting it into two separate operations x = x + 1 because that's simpler.
I think I agree that x = x + 1 *is* simpler. We can understand it by understanding the two parts separately: x+1, followed by assignment.
Whereas += requires us to understand that the syntax not only calls a dunder method __iadd__ (or __add__ if that doesn't exist), which potentially can operate in place, but it also does an assignment, all in one conceptual operation. There's a whole lot of extra complexity there.
That doesn't mean I agree with your conclusion that we ought to prefer the simpler version, let alone that the complex case (augmented assignment) is fit only for programming contests and that professionals ought to choose the simpler one.
-- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/