Pythonification of the asterisk-based collection packing/unpacking syntax

Eelco hoogendoorn.eelco at gmail.com
Sun Dec 18 09:13:37 EST 2011


On Dec 18, 1:59 am, Steven D'Aprano <steve
+comp.lang.pyt... at pearwood.info> wrote:
> On Sat, 17 Dec 2011 06:38:22 -0800, Eelco wrote:
> > Type constraints:
>
> > In case the asterisk is not used to signal unpacking, but rather to
> > signal packing, its semantics is essentially that of a type constraint.
>
> "Type constraint" normally refers to type restrictions on *input*: it is
> a restriction on what types are accepted. When it refers to output, it is
> not normally a restriction, therefore "constraint" is inappropriate.
> Instead it is normally described as a coercion, cast or conversion.
> Automatic type conversions are the opposite of a constraint: it is a
> loosening of restrictions. "I don't have to use a list, I can use any
> sequence or iterator".

Casts or conversions are a runtime concept; im talking about
declarations. That seems to be the source of your confusion.

> In iterator unpacking, it is the *output* which is a list, not a
> restriction on input: in the statement:
>
> head, *tail = sequence
>
> tail may not exist before the assignment, and so describing this as a
> constraint on the type of tail is completely inappropriate.

Yes, the variable tail is being (re)declared here. Thats exactly why I
call it a type constraint. Im not sure what the CS books have to say
on the matter, I guess this use of the term entered my lexicon through
the C# developer team. Either way, you seem to be the only one who
does not grok my intended meaning, so I suggest you try reading it
again.

> > The statement:
>
> >     head, tail = sequence
>
> > Signifies regular unpacking. However, if we add an asterisk, as in:
>
> >     head, *tail = sequence
>
> > We demand that tail not be just any python object, but rather a list.
>
> We don't demand anything, any more than when we say:
>
> for x in range(1, 100):
>
> we "demand" that x is not just any python object, but rather an int.
>
> Rather, we accept what we're given: in case of range and the for loop, we
> are given an int. In the case of extended tuple unpacking, we are given a
> list.

for x in range is syntactic sugar for a series of assignments to x; x
is an unconstrained variable that will indeed take anything it gets;
the semantics of what comes after 'x' does in no way depend on x
itself. head, tail = l and head, *tail = l mean something completely
different, and the only difference is a constraint placed on tail,
which forces the semantics to be different; the righthand side, or
what is to be assigned, is identical. Of course one can just regard it
as syntactic sugar for head, tail = unpackheadandtailaslist(l); but
the syntactic sugar achieves that same end through a type constraint
on tail. Really.

> You are jumping to conclusions about implementation details which aren't
> supported by the visible behaviour. What evidence do you have that
> iterator unpacking creates a tuple first and then converts it to a list?

You are jumping to conclusions about my opinion which aren't supported
by my visible behaviour. What evidence do you have that I ever even
said any such thing?

> > The aim of this PEP, is that this type-constraint syntax is expanded
> > upon. We should be careful here to distinguish with providing optional
> > type constraints throughout python as a whole; this is not our aim.
>
> Iterator unpacking is no more about type constraints than is len().

Because you wish to keep nitpicking about my usage of the term 'type
constraint' (even though you have not introduced an alternative term
yourself), or because you actually disagree with the content of my
message?



More information about the Python-list mailing list