Okay, I though about it some more, and I think I'm mistaken about the possibility of adding both rules to the grammar since in that case it is ambiguous whether given binds more tightly to a trailing expression or to the comp_iter. It's too bad.
On Wed, May 30, 2018 at 10:50 PM Neil Girdhar <mistersh...@gmail.com> wrote: > 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/