On Dec 13, 2:41 am, Ian Kelly <ian.g.ke...@gmail.com> wrote: > On Mon, Dec 12, 2011 at 4:40 PM, Eelco <hoogendoorn.ee...@gmail.com> wrote: > >> For a linked list, no *target and no copying is needed: > > >> head, tail = llist > > > I have no idea what this means. > > Each node of a linked list consists of a data member and a "next" > member, that holds the next node in the list. The natural container > for this and the way it is usually implemented in Python is a > 2-element tuple. For example: > > llist = ('one', ('two', ('three', ('four', None)))) > > would be a linked list as typically constructed in Python, and it can > be used in pretty much the same way that lists are used in Lisp. The > result of the operation: > > head, tail = llist > > is: > > head = 'one' > tail = ('two', ('three', ('four', None))) > > and as Terry pointed out, no copying is required to do this. I > believe deque is also implemented as a doubly-linked list, which is > probably why you keep referring to it as such, but that is an > implementation detail. When you say "linked list" in relation to > Python, the preceding is what comes to mind.
'for i in llist' is not quite going to fly is it? Thats probably the reason noone ever uses that construct; its not a proper sequence type. > >> >>>> head, deque(tail) = somedeque > > >> > Is better in every way I can think of (readability, consistence, > >> > performance) than: > >> >>>> head, *tail = somedeque > >> >>>> tail = deque(tail) > > >> But your suggestion is much worse in each way than > > >> head = somedeque.popleft() > > > No its not. First of all, its not semantically equivalent; popleft > > mutates a collection type, and collection unpacking does not; it > > creates a set of disjoint views of the collection's data. Whether its > > worse in terms of readability is debatable, but in terms of the other > > two stated metrics, your claim of it being any kind of worse is > > objectively false. > > I definitely disagree on readability. Skimming this thread as I have > been, it took me a while to get that your proposed syntax would create > a second deque sharing internal state with the original, rather than > creating a simple copy of the deque, which is what it looks like it > should do. Thats a matter of reading up on the semantics of collection unpacking. To be honest I dont even know what they are for lists, since I dont use python 3. But whatever is the case, the important thing is that the semantics should be uniform regardless of the type to be unpacked. > Incidentally, while that change is not really central to your syntax > proposal, I think it would be very messy. For example, how do you > propose keeping the length elements in sync? Inserting an item in one > may or may not affect the length of the other. If I append an item to > the end of one deque, should the other automatically be extended as > well? What if the tail node of the second deque occurs after the tail > node of the deque being appended? Does the appended element then get > inserted into the middle of the second deque (I think it would have to > be)? If I insert an element into the longer (second) deque that just > happens to be immediately after the tail of the shorter deque, does > *that* cause the shorter deque to be automatically extended? And > likewise for operations at the head of the deque. > > None of these questions have obvious answers as to the "right" way to > it, and for that reason I think this is probably best left to the user > to implement a custom deque view class with whatever semantics they > prefer. Good point. Copy-on-write semantics could be used, but really one should have several linked list types reflecting the underlying implementations. I would like to have an immutable singly linked list builtin of the standard functional type, which you can only unpack from one end and renders these issues moot, plus a builtin doubly linked list with copy-on-write or copy-on-unpacking semantics. > > Furthermore, this brings us back again to the point I raised several > > times before. Yes, obviously you can already DO these things, but NOT > > within the same uniform collection unpacking syntactic construct. > > Again, you have failed to point out what is wrong with supplying a > > type constrain to python and let it do the right thing based on that; > > to reiterate: > > > head, tail::deque = deque > > Python users generally follow the rule "explicit is better than > implicit". Setting a general constraint and letting the language "do > the right thing" is a kind of black magic that feels off because it > tends to break that rule. But that's not to say that black magic > never wins -- just look at super() and the MRO. We are not talking black magic here; we are talking about an EXPLICIT type constraint provided on the very same line. > > If you dont like the extra characters you have to type; there is of > > course such a thing as defaults. You can choose: > > head, tail:: = deque; if the type constraint is omitted, we could make > > tail a list by default, or my preferred solution, infer it from the > > right hand side type. > > I prefer the former. If it always creates a list by default, then the > programmer reading this code three years later knows exactly what the > type of tail is. If it instead infers it from the sequence being > unpacked, then the programmer is forced to infer it as well, and it > won't necessarily be obvious or even consistent. Well perhaps, but not always knowing the type of your objects at write- time is inherent to weakly typed languages; this happens all the time. Not knowing the type of the sequence to be unpacked is in a sense an asset; I can use this construct in a function, and unpack any sequence type in a manner appropriate for it. About the result of the unpacking I will know just as much as about the input to it; that they are the same type. -- http://mail.python.org/mailman/listinfo/python-list