
On Sun, Jan 16, 2022 at 10:33:41PM -0800, Christopher Barker wrote:
On Sun, Jan 16, 2022 at 7:05 PM Steven D'Aprano <steve@pearwood.info> wrote:
I never suggested adding this "for consistency".
Then what ARE you suggesting it for?
Apologies if my initial post was not clear enough: https://mail.python.org/archives/list/python-ideas@python.org/message/GRMNMW... CPython already has all the machinery needed to create constant frozensets of constants at compile time. It already implicitly optimizes some expressions involving tuples and sets into frozensets, but such optimizations are fragile and refactoring your code can remove them. Ironically, that same optimization makes the explicit creation of a frozenset needlessly inefficient. See also b.p.o. #46393. The only thing we need in order to be able to explicitly create frozensets efficiently, without relying on fragile, implicit, implementation-dependent peephole optimizations which may or may not trigger, and without triggering the usual global+builtins name lookup, is (I think) syntax for a frozenset display. That would make the creation of frozensets more efficient, possibly encourage people who currently are writing slow and inefficient code like targets = (3, 5, 7, 11, 12, 18, 27, 28, 30, 35, 57, 88) if n in targets: do_something() to use a frozenset, as they probably should already be doing.
As far as I can tell, it would be a handy shorthand.
If you consider tuple, list and dict displays to be a handy shortcut, then I guess this would be too :-)
And you had suggested it could result in more efficient bytecode, but I think someone else thought that wasn't the case.
I see no reason why it wouldn't lead to more efficient bytecode, at least sometimes.
But what does that matter? are they heavenly used in any common code?
Personally, I think my code using frozensets is extremely heavenly :-) I doubt that frozensets are, or ever will be, as common as lists or dicts. In that sense, sets (frozen or otherwise) are, I guess, "Second Tier" data structures: - first tier are lists, tuples, dicts; - second tier are sets, deques etc. Or possibly "tier and a half" in that unlike deques they are builtins, which suggest that they are somewhat more important. In the top level of the stdlib (not dropping down into packages or subdirectories), I count 29 calls to frozenset. (Compared to 14 calls to deque, so on mere call count, I would say frozenset is twice as important as deque :-) Out of those 29 calls, I think that probably 13 would be good candidates to use a frozenset display form (almost half). For example: ast.py: binop_rassoc = frozenset(("**",)) # f{("**",)} asyncore.py: ignore_log_types = frozenset({'warning'}) # f{'warning'} Not all of them are purely literals, e.g. asyncore.py: _DISCONNECTED = frozenset({ECONNRESET, ENOTCONN, ...}) would still have to generate the frozenset at runtime, but it wouldn't need to look up the frozenset name to do so so there would still be some benefit. If we were particularly keen, that might go up to 19 out of the 29. The benefit is not huge. This is not list comprehensions or decorator syntax, which revolutionized the way we write Python, it is an incremental improvement. If the compiler didn't already have the machinery in place for building compile-time constant frozensets, this might not be worth the effort. But since we do, the cost of adding a frozenset display is relatively low (most of the work is already done, yes?) and so the benefit needs only to be small to justify the small(?) amount of work needed. -- Steve