Inspired by this enhancement request:

https://bugs.python.org/issue46393

I thought it might be time to revist the idea of a frozenset display. 
This has been discussed a few times before, such as here:

https://mail.python.org/pipermail/python-ideas/2018-July/051902.html

We have displays for the most important builtin data structures:

- lists  [1, 2, 3]
- tuples (1, 2, 3)
- dicts  {1: 0, 2: 0, 3: 0}
- sets   {1, 2, 3}

(as well as literals for ints, floats, strings and bytes)

but not for frozensets. So the only way to guarantee that you have a 
frozenset is to explicitly call the builtin, which is not only a runtime 
call rather than a compile-time operation, but can be monkey-patched or 
shadowed.

CPython already has some neat optimizations in place to use frozensets 
instead of sets, for example:

>>> import dis
>>> dis.dis("x in {1, 2, 3}")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (frozenset({1, 2, 3}))
              4 CONTAINS_OP              0
              6 RETURN_VALUE

and the compiler can build frozensets of literals as a constant. 
Ironically, this means that actually making a frozenset explicitly does 
far more work than needed:

>>> dis.dis("frozenset({1, 2, 3})")
  1           0 LOAD_NAME                0 (frozenset)
              2 BUILD_SET                0
              4 LOAD_CONST               0 (frozenset({1, 2, 3}))
              6 SET_UPDATE               1
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

Got that? To create a frozenset of literals, first the compiler creates 
a frozenset constant containing what you wanted. Then at runtime, it:

- looks up frozenset in globals and builtins;
- loads the pre-prepared frozenset (which is exactly what we want);
- creates a new set from that frozenset;
- calls the frozenset() function on that set to create a new frozenset
  that duplicates the pre-prepared one;
- and finally garbage-collects the temporary set.

So to get the frozenset we want, we start with the frozenset we want, 
and make an unnecessary copy the long way o_O

If you didn't know that every step in that song and dance routine was 
necessary, it would seem ludicrously wasteful.

If we had a frozenset display, we could avoid most of that work, 
optimizing that down to a LOAD_CONST like this:

>>> dis.dis('(1, 2, 3)')
  1           0 LOAD_CONST               0 ((1, 2, 3))
              2 RETURN_VALUE

It seems to me that all of the machinery to make this work already 
exists. The compiler already knows how to create frozensets at 
compile-time, avoiding the need to lookup and call the frozenset() 
builtin. All we need is syntax for a frozenset display.

How does this work for you?

    f{1, 2, 3}


-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/GRMNMWUQXG67PXXNZ4W7W27AQTCB6UQQ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to