diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 42a581bceee..37df8f3aa0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -677,6 +677,7 @@ peps/pep-0798.rst @JelleZijlstra peps/pep-0799.rst @pablogsal peps/pep-0800.rst @JelleZijlstra peps/pep-0801.rst @warsaw +peps/pep-0802.rst @AA-Turner # ... peps/pep-2026.rst @hugovk # ... diff --git a/peps/pep-0802.rst b/peps/pep-0802.rst new file mode 100644 index 00000000000..1715b0e8984 --- /dev/null +++ b/peps/pep-0802.rst @@ -0,0 +1,275 @@ +PEP: 802 +Title: Display Syntax for the Empty Set +Author: Adam Turner +Discussions-To: Pending +Status: Draft +Type: Standards Track +Created: 08-Aug-2025 +Python-Version: 3.15 + + +Abstract +======== + +We propose a new notation, ``{/}``, to construct and represent the empty set. +This is modelled after the corresponding mathematical symbol ':math:`\emptyset`'. + +This complements the existing notation for empty tuples, lists, and +dictionaries, which use ``()``, ``[]``, and ``{}`` respectively. + + +Motivation +========== + +Sets are currently the only built-in collection type that have a +:ref:`display syntax `, +but no notation to express an empty collection. +The :ref:`Python Language Reference ` notes this, stating: + + An empty set cannot be constructed with ``{}``; + this literal constructs an empty dictionary. + +This can be confusing for beginners, especially those coming to the language +from a scientific or mathematical background, where sets may be in more common +use than dictionaries or maps. + +A syntax notation for the empty set has the important benefit of not requiring +a name lookup (unlike ``set()``). +``{/}`` will always have a consistent meaning, improving teachability +of core concepts to beginners. +For example, users must be careful not to use ``set`` as a local variable name, +as doing so prevents constructing new sets. +This can be frustrating as beginners may not know how to recover the +:py:class:`set` type if they have overriden the name: +techniques to do so (e.g. ``type({1}-{1})``) are not immediately obvious. + +Finally, this may be helpful for users who do not speak English, +as it provides a culture-free notation for a common data structure +that is built into the language. + + +Rationale +========= + +Sets were introduced to Python 2.2 via :pep:`218`, which did not include +set notation, but discussed the idea of ``{-}`` for the empty set: + + The PEP originally proposed ``{1,2,3}`` as the set notation and ``{-}`` for + the empty set. Experience with Python 2.3's ``sets.py`` showed that + the notation was not necessary. Also, there was some risk of making + dictionaries less instantly recognizable. + +Python 3.0 introduced set literals (:pep:`3100`), but again chose not to +introduce notation for the empty set, which was omitted out of pragmatism +(`python-3000, April 2006`_, `python-3000, May 2006`_). + +Since then, the topic has been discussed several times, +with various proposals, including: + +#. Changing ``{}`` to mean an empty set and using ``{:}`` for an empty dictionary + (`python-ideas, January 2008`_, `Discourse, March 2023`_) +#. A Unicode character (e.g. ``∅`` or ``ϕ``) + (`python-ideas, April 2021`_) +#. ``<>`` + (`python-ideas, November 2010`_, `Discourse, December 2024`_) +#. ``s{}`` + (`python-ideas, June 2009`_) +#. ``{*()}``, perhaps optimising to compile this to the ``BUILD_SET`` opcode + (`Discourse, August 2025 (#37)`_) +#. ``{-}`` + (`python-ideas, August 2020`_) +#. ``{,}`` + (`Discourse, August 2025`_) +#. ``{/}`` + (`python-ideas, January 2008`_) +#. ``set()`` (i.e. doing nothing) + +The authors propose ``{/}`` as the notation, +being in their opinion the best of these options. +It is simple and concise, with the benefit of resembling the mathematical +notation for the empty set, :math:`\emptyset`. +This makes it an easier mnemonic to explain than several in the language, +such as ``**`` for exponentiation or ``@`` for matrix multiplication. + +The ``{/}`` notation was also the most popular in a `recent Discourse poll`_, +selected by 41% of respondents overall and 60% of those voting for a new syntax. + +Brief summaries for the other proposals may be found in `Rejected Ideas`_. + + +Specification +============= + +The grammar for set displays will become: + +.. productionlist:: python-grammar + set_display: "{" ("/" | flexible_expression_list | comprehension) "}" + +``{/}`` will become the default syntax for the empty set. + +.. code-block:: python + + >>> type({/}) + + >>> {/} == set() + True + +The representation and string forms of the empty set will change to ``'{/}'``. + +.. code-block:: python + + >>> repr({/}) + '{/}' + >>> str({/}) + '{/}' + +There will be no behavioural changes to :py:class:`set` objects. + + +Backwards Compatibility +======================= + +Code that relies on the ``repr()`` or ``str()`` of the empty set +will no longer work, because the representation will change. + +There will be no other backwards incompatibile changes, +all current constructors for the empty set will continue to work, +and the behaviour of the :py:class:`set` type will remain unchanged. + + +Security Implications +===================== + +None. + + +How to Teach This +================= + +All users can be taught that ``{/}`` is the new spelling for ``set()``, +and that it is equivalent in all other ways. +To help reinforce this, we will update the documentation to use ``{/}`` +instead of ``set()``, including the tutorial, standard libary modules, +and the Python Language Reference. + +For new users, sets can be introduced through syntax, noting that the four +built-in collection types with syntax all have empty forms: +``()``, ``[]``, ``{/}``, and ``{}``. + +The empty set uses a forwards slash to differentiate it from +an empty dictionary. +It uses this syntax because it looks like the mathematical symbol +for the empty set (':math:`\emptyset`'). +This can be used as a helpful mnemonic when teaching beginners, +especially those that have a maths or science background. + + +Reference Implementation +======================== + +Forthcoming. + + +Rejected Ideas +============== + +Change ``{}`` to mean an empty set and use ``{:}`` for an empty dictionary +-------------------------------------------------------------------------- + +This would be an entirely backwards incompatible change, +all current empty :py:class:`dict` objects would become sets. + +Use a Unicode character (e.g. ``∅`` or ``ϕ``) +--------------------------------------------- + +The Unicode character 'U+2205 ∅ EMPTY SET' is not currently a valid identifier. +Introducing a Unicode character as syntax would be hard to use, +as it does not appear on standard keyboards. + +Using other characters that look like ∅, such as 'U+03C6 ϕ GREEK SMALL LETTER +PHI' or 'U+00D8 Ø LATIN CAPITAL LETTER O WITH STROKE', would be more confusing +with the same drawbacks of using a Unicode character. + +Use the ``<>`` syntax +--------------------- + +It does not have a resemblance to the syntax for non-empty sets. +This would be harder to explain than this PEP's proposal. + +This syntax further has historic use as the inequality operator, +which can still be accessed via ``from __future__ import barry_as_FLUFL``. +Using both the ``barry_as_FLUFL`` future import and ``<>`` for the empty set +would lead to parser ambiguity: what would ``<> <> <>`` mean? + +Use the ``s{}`` syntax +---------------------- + +This syntax may cause confusion with ``s`` as a local variable. +The only current use of prefixes of this kind is for string literals. +This would be harder to explain than this PEP's proposal. + +Use the ``{*()}`` syntax +------------------------ + +This relies on unpacking the empty tuple into a set, creating an empty set. +This has the benefit of support since Python 3.5 (:pep:`448`), but is unwieldy +and complicated to explain; it was not designed for this purpose. + +Use the ``{-}`` syntax +---------------------- + +This syntax was originally proposed in :pep:`218`, +but removed from the PEP before it was accepted. +The authors prefer ``{/}`` due to the resemblance to :math:`\emptyset`. + +Use the ``{,}`` syntax +---------------------- + +This is the authors' next preferred option. +However, if a single comma were to be used to represent an empty collection, +it may be confusing why this could not be used for empty tuples or lists. +In time, there might be proposals to add support for ``[,]`` and ``(,)``. +This conflicts with the general principle that +'*there should be one-- and preferably only one --obvious way to do it*'. +Having a visibly different form, in ``{/}``, helps to reinforce the idea +that the syntax for the empty set is a special case, rather than a general rule +for all empty collections. + + +Open Issues +=========== + +None. + + +Acknowledgements +================ + +* Chris Angelico, Dominykas Grigonis, Ben Hsing, James Webber, + and other contributors to recent Discourse topics. +* Hugo van Kemenade, for helpful feedback on a draft of the PEP. + + +Footnotes +========= + +.. _Discourse, August 2025 (#37): https://discuss.python.org/t/101197/37 +.. _Discourse, August 2025: https://discuss.python.org/t/101197 +.. _Discourse, December 2024: https://discuss.python.org/t/73235 +.. _Discourse, March 2023: https://discuss.python.org/t/25213 +.. _explicitly deferred: https://mail.python.org/pipermail/python-3000/2006-May/001599.html +.. _python-3000, April 2006: https://mail.python.org/pipermail/python-3000/2006-April/001286.html +.. _python-3000, May 2006: https://mail.python.org/pipermail/python-3000/2006-May/001666.html +.. _python-ideas, April 2021: https://mail.python.org/archives/list/python-ideas@python.org/message/X4TX2HDNKDJ7PVZL3DVI5QD2MIMRHKO4/ +.. _python-ideas, August 2020: https://mail.python.org/archives/list/python-ideas@python.org/message/QOBONXUPUMC3ULCGJU6FVHOCIZQDT45W/ +.. _python-ideas, January 2008: https://mail.python.org/archives/list/python-ideas@python.org/thread/IBMTTESRSF5755LNMVTUMHHABKOBSPUZ/#IBMTTESRSF5755LNMVTUMHHABKOBSPUZ +.. _python-ideas, June 2009: https://mail.python.org/archives/list/python-ideas@python.org/thread/AMWKPS54ZK6X2FI7NICDM6DG7LERIJFV/#AMWKPS54ZK6X2FI7NICDM6DG7LERIJFV +.. _python-ideas, November 2010: https://mail.python.org/archives/list/python-ideas@python.org/thread/N7CHDYXW2FYHDJ5BTP7CCC5HLAIINOVH/#N7CHDYXW2FYHDJ5BTP7CCC5HLAIINOVH +.. _recent Discourse poll: https://discuss.python.org/t/101197/15 + + +Copyright +========= + +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive.