<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 9, 2015, at 7:29 PM, Neil Girdhar <<a href="mailto:mistersheik@gmail.com" class="">mistersheik@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">For some reason I can't seem to reply using Google groups, which is is telling "this is a read-only mirror" (anyone know why?)  Anyway, I'm going to answer as best I can the concerns.</div><div class=""><br class=""></div><div class="">Antoine said:</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">To be clear, the PEP will probably be useful for one single line of <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">Python code every 10000. This is a very weak case for such an intrusive <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">syntax addition. I would support the PEP if it only added the simple <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">cases of tuple unpacking, left alone function call conventions, and <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">didn't introduce **-unpacking. </span></blockquote><div class=""><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class=""><br class=""></span></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">To me this is more of a syntax simplification than a syntax addition.  For me the **-unpacking is the most useful part. Regarding utility, it seems that a many of the people on r/python were pretty excited about this PEP: <a href="http://www.reddit.com/r/Python/comments/2synry/so_8_peps_are_currently_being_proposed_for_python/" class="">http://www.reddit.com/r/Python/comments/2synry/so_8_peps_are_currently_being_proposed_for_python/</a></font></div><div class=""><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class=""><br class=""></span></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">—</font></div><div class=""><font face="Arial, Helvetica, sans-serif" class=""><br class=""></font></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">Victor noticed that there's a mistake with the code:</font></div><div class=""><font face="Arial, Helvetica, sans-serif" class=""><br class=""></font></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">>>> ranges = [range(i) for i in range(5)] <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">>>> [*item for item in ranges] <br class=""></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">[0, 0, 1, 0, 1, 2, 0, 1, 2, 3] </span></blockquote><div class=""><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class=""><br class=""></span></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">It should be a range(4) in the code.  The "*" applies to only item.  It is the same as writing:</font></div><div class=""><font face="Arial, Helvetica, sans-serif" class=""><br class=""></font></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">[*range(0), *range(1), *range(2), *range(3), *range(4)]</font></div><div class=""><font face="Arial, Helvetica, sans-serif" class=""><br class=""></font></div><div class=""><font face="Arial, Helvetica, sans-serif" class="">which is the same as unpacking all of those ranges into a list.</font></div><div class=""><font face="Arial, Helvetica, sans-serif" class=""><br class=""></font></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">> function(**kw_arguments, **more_arguments) </span><br style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class=""><span style="font-family: Arial, Helvetica, sans-serif; font-size: 13px;" class="">If the key "key1" is in both dictionaries, more_arguments wins, right? </span></blockquote><div class=""><br class=""></div><div class="">There was some debate and it was decided that duplicate keyword arguments would remain an error (for now at least).  If you want to merge the dictionaries with overriding, then you can still do:</div><div class=""><br class=""></div><div class="">function(**{**kw_arguments, **more_arguments})</div><div class=""><br class=""></div><div class="">because **-unpacking in dicts overrides as you guessed.</div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Feb 9, 2015 at 7:12 PM, Donald Stufft<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:donald@stufft.io" target="_blank" class="">donald@stufft.io</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><span class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 9, 2015, at 4:06 PM, Neil Girdhar <<a href="mailto:mistersheik@gmail.com" target="_blank" class="">mistersheik@gmail.com</a>> wrote:</div><br class=""><div class=""><div dir="ltr" class=""><div dir="ltr" class="">Hello all,<div class=""><br class=""></div><div class="">The updated PEP 448 (<a href="https://www.python.org/dev/peps/pep-0448/" target="_blank" class="">https://www.python.org/dev/peps/pep-0448/</a>) is implemented now based on some early work by Thomas Wouters (in 2008) and Florian Hahn (2013) and recently completed by Joshua Landau and me.</div><div class=""><br class=""></div><div class="">The issue tracker <a href="http://bugs.python.org/issue2292" target="_blank" class="">http://bugs.python.org/issue2292</a>  has  a working patch.  Would someone be able to review it?</div><div class=""><br class=""></div></div></div></div></blockquote><br class=""></div></span><div class=""><div class="">I just skimmed over the PEP and it seems like it’s trying to solve a few different things:</div><div class=""><br class=""></div><div class="">* Making it easy to combine multiple lists and additional positional args into a function call</div><div class="">* Making it easy to combine multiple dicts and additional keyword args into a functional call</div><div class="">* Making it easy to do a single level of nested iterable "flatten".</div></div></div></blockquote><div class=""><br class=""></div><div class="">I would say it's:</div><div class="">* making it easy to unpack iterables and mappings in function calls</div><div class="">* making it easy to unpack iterables  into list and set displays and comprehensions, and</div><div class="">* making it easy to unpack mappings into dict displays and comprehensions.</div><div class=""><br class=""></div><div class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><div class=""><br class=""></div><div class="">Looking at the syntax in the PEP I had a hard time detangling what exactly it was doing even with reading the PEP itself. I wonder if there isn’t a way to combine simpler more generic things to get the same outcome.</div><div class=""><br class=""></div><div class="">Looking at the "Making it easy to combine multiple lists and additional positional args into a  function call" aspect of this, why is:</div><div class=""><br class=""></div><div class="">print(*[1], *[2], 3) better than print(*[1] + [2] + [3])?</div><div class=""><br class=""></div><div class="">That's already doable in Python right now and doesn't require anything new to handle it.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Admittedly, this wasn't a great example.  But, if [1] and [2] had been iterables, you would have to cast each to list, e.g.,</div><div class=""><br class=""></div><div class="">accumulator = []</div><div class="">accumulator.extend(a) <br class=""></div><div class="">accumulator.append(b)<br class=""></div><div class="">accumulator.extend(c)<br class=""></div><div class="">print(*accumulator)</div><div class=""><br class=""></div><div class="">replaces</div><div class=""><br class=""></div><div class="">print(*a, b, *c)</div><div class=""><br class=""></div><div class="">where a and c are iterable.  The latter version is also more efficient because it unpacks only a onto the stack allocating no auxilliary list.</div></div></div></div></div></blockquote><div><br class=""></div><div>Honestly that doesn’t seem like the way I’d write it at all, if they might not be lists I’d just cast them to lists:</div><div><br class=""></div><div>print(*list(a) + [b] + list(c))</div><div><br class=""></div><div>But if casting to list really is that big a deal, then perhaps a better solution is to simply make it so that something like ``a_list + an_iterable`` is valid and the iterable would just be consumed and +’d onto the list. That still feels like a more general solution and a far less surprising and easier to read one.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><div class=""><br class=""></div><div class="">Looking at the "making it easy to do a single level of nsted iterable 'flatten'"" aspect of this, the example of:</div><div class=""><br class=""></div><div class="">>>> ranges = [range(i) for i in range(5)]</div><div class="">>>> [*item for item in ranges]</div><div class="">[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]</div><div class=""><br class=""></div><div class="">Conceptually a list comprehension like [thing for item in iterable] can be mapped to a for loop like this:</div><div class=""><br class=""></div><div class="">result = []</div><div class="">for item in iterable:</div><div class="">   <span class="Apple-converted-space"> </span>result.append(thing)</div><div class=""><br class=""></div><div class="">However [*item for item in ranges] is mapped more to something like this:</div><div class=""><br class=""></div><div class="">result = []</div><div class="">for item in iterable:</div><div class="">   <span class="Apple-converted-space"> </span>result.extend(*item)</div><div class=""><br class=""></div><div class="">I feel like switching list comprehensions from append to extend just because of a * is really confusing and it acts differently than if you just did *item outside of a list comprehension. I feel like the itertools.chain() way of doing this is *much* clearer.</div><div class=""><br class=""></div><div class="">Finally there's the "make it easy to combine multiple dicts into a function call" aspect of this. This I think is the biggest thing that this PEP actually adds, however I think it goes around it the wrong way. Sadly there is nothing like [1] + [2] for dictionaries. The closest thing is:</div><div class=""><br class=""></div><div class="">kwargs = dict1.copy()</div><div class="">kwargs.update(dict2)</div><div class="">func(**kwargs)</div><div class=""><br class=""></div><div class="">So what I wonder is if this PEP wouldn't be better off just using the existing methods for doing the kinds of things that I pointed out above, and instead defining + or | or some other symbol for something similar to [1] + [2] but for dictionaries. This would mean that you could simply do:</div><div class=""><br class=""></div><div class="">func(**dict1 | dict(y=1) | dict2)</div><div class=""><br class=""></div><div class="">instead of</div><div class=""><br class=""></div><div class="">dict(**{'x': 1}, y=2, **{'z': 3})</div><div class=""><br class=""></div><div class="">I feel like not only does this genericize way better but it limits the impact and new syntax being added to Python and is a ton more readable.</div></div></div></blockquote></div></div></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>Honestly the use of * and ** in functions doesn’t bother me a whole lot, though i don’t see much use for it over what’s already available for lists (and I think doing something similarly generic for mapping is a better idea). What really bothers me is these parts:</div><div><br class=""></div><div><div class="">* making it easy to unpack iterables  into list and set displays and comprehensions, and</div><div class="">* making it easy to unpack mappings into dict displays and comprehensions.</div><div class=""><br class=""></div><div class="">I feel like these are super wrong and if they were put in I’d probably end up writing a linter to disallow them in my own code bases.</div><div class=""><br class=""></div><div class="">I feel like adding a special case for * in list comprehensions breaks the “manually expanded” version of those. Switching from append to extend inside of a list comprehension because of a * doesn’t make any sense to me. I can’t seem to construct any for loop that mimics what this PEP proposes as [*item for item in iterable] without fundamentally changing the operation that happens in each loop of the list comprehension.</div><div class=""><br class=""></div></div><div><br class=""></div></div><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">---</div><div class="">Donald Stufft</div><div class="">PGP: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA</div></div></div>
</div>
<br class=""></body></html>