On 2018-05-12 18:24, Steven D'Aprano wrote: > 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, > > [snip] > > 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?
Your interpretation of the argument you quote, as I understand it, is that "`given` is simpler than `:=`". I interpreted it as, and would argue myself, more like "`given` makes *the code that uses it* simpler". The reason the `given` syntax might be simpler has nothing to do with the number of syntactic elements (brainfuck is down the hall...). Rather, it is that `given` separates things: if m.group(2) in words given m = word_re.match(s): versus: if (m := word_re.match(s)).group(2) in words: In the `:=` version, the assignment is embedded in the expression. It's different. Most of the time it will save at least a few characters. But it's not obviously--and certainly not objectively--simpler. One somewhat concrete difference I can think of is that in expressions that refer to the result multiple times, the `:=` assignment must always be positioned such that it is the first to be evaluated, moving around should that ever change. In cases where evaluation depends on runtime information (if-else, and, or), I'm not actually sure what you would do. In general, I feel like you're focusing on the simplicity or otherwise of the operator itself, rather than whether it has a simplifying effect on code that uses it. As you say in part 2 (which arrived while I was still taking forever to write this; sorry if it reads a bit confused), we'll learn the syntax, eventually. What's not so explicitly spelled out is that we'll be reading new code that uses it forever. > average = 0 smooth_signal = [(average := (1-decay)*average + > decay*x) for x in signal] assert average == smooth_signal[-1] Like, holy smoke, man. Sure, `:=` is probably better for cramming side-effects into list comprehensions. Please don't cram side-effects into list comprehensions. > 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] What is it with the cramming side-effects into list comprehensions‽ Do you realise itertools.accumulate exists? See the OP: On 2018-05-04 13:06, Nick Coghlan wrote: > 3. Sharing values between filtering clauses and result expressions in > comprehensions: > > result = [(x, y, x/y) for x in data if (y := f(x))] I don't have a more concrete example of this to hand, mostly because I can't do this today, and faking it is hard enough (I didn't even know about the `for value in [stuff]` hack until this thread) that I just write for loops. On 2018-05-12 18:24, Steven D'Aprano wrote: > 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. While I'm not sorry that I can do `x += 1`, it does have a substantial cost--one that is perhaps justified by the fact that it's *not* equivalent to `x = x + 1`, and that the possibilities it opens up are both useful and easy to understand. It's not simpler in and of itself, but that's not really the issue. On 2018-05-12 19:27, Steven D'Aprano wrote: > What you probably want is the second version: > > (a := c.d()).b(a) > > which of course looks like utter crap. It might look better if we > use at least half-way sensible variable names and a more realistic > looking example, instead of obfuscated one-letter names. > > (widget := widget_builder.new(*args)).method(widget) I believe that that's missing the point: to wit, in x.method(y) is `x` or `y` evaluated first? I didn't know. I don't think the order is documented anywhere or guaranteed not to change. I don't know what other languages do in general, though I know in C it's explicitly unspecified. So, sure, you can do this fine with `:=`. But it forces your code to depend on what I'd regard as a subtlety of the implementation.
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/