Updated proposal:
frozenset
- Empty:
frozenset() - With items:
${1, 2} - Comprehension:
${x for x in range(10)}
frozendict
- Empty:
frozendict() - With items:
${1: 2, 3: 4} - Comprehension:
${x: 1 for x in range(1)}
Main motivation:
- Simplicty: we want to endorse immutable objects usage, especially for free-threading and subinterpreters. Simple syntax propomotes this
- Performance: we don’t want to create intermediate objects to create a builtin type. Special syntax allows to optimize this perfectly
In my opinion there are several important questions if we want to start working on this.
- I decided to go with
$(because immutablity is the real deal). It does not look similar to anything else, likef{}looks similar tof'', it can be scaled to$(x for x in range(2))which would mean tuple comprehension, if we would want this. It can be also added to other data types in the future. Whilefcan’t be used in cases likef[]andf(), because it is a valid syntax already. - Should we really go for empty object literals? Looks like
set(),frozenset()andfrozendict()calls can be good enough as the empty objects. I propose limiting the scope of this proposal to literals and comprehensions only. We can later address the empty objects separately in the next proposal. It would be easier to get the approvals for the smallest piece of new syntax
- How it should be implemented technically. Currently, there’s an optimization built on top if
INTRINSICforINTRINSIC_BUILD_FROZENSET. Should we build new opcodes or go forINTRINSIC? Should we plan for any future optimizations beforehand? - What C-API would we need? This is a very hot topic for
PyFrozenDictAPI. Currently it does not have a way to build objects interactively. So, we would first likely need to addPyFrozenDict_FromDictStealAPI to make a dict with existing APIs and convert it tofrozendictthe most efficient way. This is the case becausePyDict_*mutation APIs can’t be used withPyFronzenDict. The same is not the case forfrozenset, it can use mutatingPySet_*APIs. - Analyze potential syntax conflicts in lexer / parser with
fprefix for strings / frozen objects (if we decide to go with this prefix) - Provide perf numbers: how much faster we can optimize the workflow with our design, compared to older forms like
frozendict({1: 2})andfrozenset(x for x in range(10)) - Find other core devs who would like and support this idea

Everyone’s feedback is welcome! ![]()