On Wed, May 30, 2018 at 9:02 PM Steven D'Aprano <st...@pearwood.info> wrote:
> On Thu, May 31, 2018 at 10:05:33AM +1000, Chris Angelico wrote: > > On Thu, May 31, 2018 at 9:53 AM, Steven D'Aprano <st...@pearwood.info> > wrote: > > >> There is no nice, equivalent := version as far as I can tell. > > > > > > Given (pun intended) the fact that you only use transformed_b in a > > > single place, I don't think it is necessary to use := at all. > > > > > > z = {a: transform(b) for b in bs for a in as_} > > > > > > But if you really insist: > > > > > > # Pointless use of := > > > z = {a: (transformed_b := transform(b)) for b in bs for a in as_} > > > > > > > That's the subtlety of the 'given' usage here. You fell for the same > > trap I did: thinking "it's only used once". > > But it is only used once. I meant once per loop. > > It isn't used in the "for a in as_" inner loop, there's no "if > transformed_b" condition, and it only is used once in the key:value part > of the comprehension. > > > > Actually, what he has is equivalent to: > > > > z = {a: tb for b in bs for tb in [transform(b)] for a in as_} > > Which also uses tb only once, making it a Useless Use Of Assignment. > > (I assume we're not calling transform() for some side-effect, like > logging a message, or erasing your hard drive.) > > > > which means it evaluates transform(b) once regardless of the length of > > as_. > > Ah yes, I see what you mean. Expanded to a loop: > > for b in bs: > tb = transform(b) > for a in as_: > z[a] = tb > > > It's a little ugly, but there's a trick I already use today: > > py> [x+y for x in "abc" if print(x) or True for y in "de"] > a > b > c > ['ad', 'ae', 'bd', 'be', 'cd', 'ce'] > > So we can adapt that to assignment instead of output: > > # Don't do this! > z = {a: tb for b in bs if (tb := transform(b)) or True for a in as_} > > But I wouldn't do that. If I'm concerned about the call to transform > (because it is super expensive, say) then I set up a pipeline: > > tbs = (transform(b) for b in bs) # or map(transform, bs) > z = {a: tb for tb in tbs for a in as_} > > The first generator comprehension can be easily embedded in the other: > > z = {a: tb for tb in (transform(b) for b in bs) for a in as_} > > This makes it super-obvious that transform is called for each b, not for > each (b, a) pair, it works today, and there's no assignment expression > needed at all. > > Assignment expressions should not be about adding yet a third way to > solve a problem that already has a perfectly good solution! ("Expand to > a loop statement" is not a *perfectly* good solution.) To showcase > assignment expressions, we should be solving problems that don't have a > good solution now. > > I'm still not convinced that Neil's "given" example will even work (see > below) but *if he is right* that it does, perhaps that's a good reason > to prefer the simpler := assignment expression syntax, since we're > less likely to use it in confusing ways. > > > > But it's really REALLY not obvious. > > But is it even legal? > > As I understand it, "given" is an expression, not an addition to > comprehension syntax. In that case, I don't think Neil's example will > work at all, for reasons I've already stated. > > If that's not the case, then until somebody tells me what this new > comprehension syntax means, and what it looks like, I have no idea what > is intended. > > Which of these can we write, and what do they do? > Great question. The trick is to just write them as a sequence of statements without changing the order except to put the expression last. > > [expression given name=something for x in seq] > retval = [] name = something for x in seq: retval.append(expression) return retval > > [expression for x given name=something in seq] > this one doesn't make sense. [expression for x in seq given name=something] > > retval = [] for x in seq: name = something retval.append(expression) return retval > [expression for x in seq if given name=something condition] > > this one doesn't make sense. > [expression for x in seq if condition given name=something] > > retval = [] for x in seq: if condition: name = something retval.append(expression) return retval and of course, the original proposal expression given name=something means: name = something retval = expression return retval > > -- > 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/ > > -- > > --- > You received this message because you are subscribed to a topic in the > Google Groups "python-ideas" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/python-ideas/keaR3FudcwQ/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > python-ideas+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/