
On 31 July 2017 at 04:31, Paul Moore <p.f.moore@gmail.com> wrote:
On 30 July 2017 at 16:24, Nick Coghlan <ncoghlan@gmail.com> wrote:
Rather than being about any changes on that front, these threads are mostly about making it possible to write that first line as:
MyNT = type(implicitly_typed_named_tuple_factory(foo=None, bar=None))
Is that really true, though? There's a lot of discussion about whether ntuple(x=1, y=2) and ntuple(y=2, x=1) are equal (which implies they are the same type).
No, they're different types, because the requested field order is different, just as if you made two separate calls to "collections.namedtuple". If you want them to be the same type, so that the parameter order in the second call gets ignored, then you need to ask for that explicitly (either by using "collections.namedtuple" directly, or by calling type() on an implicitly typed instance), or else by keeping the field order consistent.
If there's any way they can be the same type, then your definition of MyNT above is inherently ambiguous, depending on whether we've previously referred to implicitly_typed_named_tuple_factory(bar=None, foo=None).
This is why any implicit type definition would *have* to use the field order as given: anything else opens up the opportunity for action-at-a-distance that changes the field order based on the order in which instances are created. (Even without that concern, you'd also get a problematic combinatorial expansion when searching for matching existing field definitions as the number of field names increases)
For me, the showstopper with regard to this whole discussion about ntuple(x=1, y=2) is this key point - every proposed behaviour has turned out to be surprising to someone (and not just in a "hmm, that's odd" sense, but rather in the sense that it'd almost certainly result in bugs as a result of misunderstood behaviour).
I suspect the only way it would make sense is if the addition was made in tandem with a requirement that the builtin dictionary type be insertion ordered by default. The reason I say that is that given such a rule, it would *consistently* be true that: tuple(dict(x=1, y=2).items()) != tuple(dict(y=2, y=1).items()) Just as this is already reliably true in Python 3.6 today: >>> from collections import OrderedDict >>> x_first = tuple(OrderedDict(x=1, y=2).items()) >>> y_first = tuple(OrderedDict(y=2, x=1).items()) >>> x_first != y_first True >>> x_first (('x', 1), ('y', 2)) >>> y_first (('y', 2), ('x', 1)) In both PyPy and CPython 3.6+, that's actually true for the builtin dict as well (since their builtin implementations are order preserving and that's now a requirement for keyword argument and class execution namespace handling). That way, the invariant that folks would need to learn would just be: ntuple(x=1, y=2) == tuple(dict(x=1, y=2).values()) ntuple(y=2, x=1) == tuple(dict(y=2, x=1).values()) rather than the current: from collections import OrderedDict auto_ntuple(x=1, y=2) == tuple(OrderedDict(x=1, y=2).values()) auto_ntuple(y=2, x=1) == tuple(OrderedDict(y=2, x=1).values()) (Using Python 3.6 and auto_ntuple from https://gist.github.com/ncoghlan/a79e7a1b3f7dac11c6cfbbf59b189621#file-auto_... ) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia