Skip to content

Commit

Permalink
PEP 653: Fix example. Use get(key, sentinel) instead of __getitem__(k…
Browse files Browse the repository at this point in the history
…ey) for mappings. (#1902)
  • Loading branch information
markshannon authored Mar 30, 2021
1 parent 0a0e7a3 commit c029c02
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions pep-0653.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ By allowing classes to choose which kinds of pattern they match, other classes c
For example, using ``sympy``, we might want to write::

# a*a == a**2
case Mul(args=[a, b]) if a == b:
case Mul(args=[Symbol(a), Symbol(b)]) if a == b:
return Pow(a, 2)

Which requires the sympy class ``Symbol`` to "self" match.
Expand Down Expand Up @@ -273,14 +273,16 @@ A pattern not including a double-star pattern::

translates to::

$sentinel = object()
$kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0:
FAIL
if not $value.keys() >= $KEYWORD_PATTERNS.keys():
FAIL
# $KEYWORD_PATTERNS is a meta-variable mapping names to variables.
for $KEYWORD in $KEYWORD_PATTERNS:
$KEYWORD_PATTERNS[$KEYWORD] = $value[QUOTE($KEYWORD)]
$tmp = $value.get(QUOTE($KEYWORD), $sentinel)
if $tmp is $sentinel:
FAIL
$KEYWORD_PATTERNS[$KEYWORD] = $tmp

Example: [4]_

Expand All @@ -293,10 +295,10 @@ translates to::
$kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0:
FAIL
if not $value.keys() >= $KEYWORD_PATTERNS.keys():
FAIL:
# $KEYWORD_PATTERNS is a meta-variable mapping names to variables.
$tmp = dict($value)
if not $tmp.keys() >= $KEYWORD_PATTERNS.keys():
FAIL:
for $KEYWORD in $KEYWORD_PATTERNS:
$KEYWORD_PATTERNS[$KEYWORD] = $tmp.pop(QUOTE($KEYWORD))
$DOUBLE_STARRED_PATTERN = $tmp
Expand Down Expand Up @@ -502,15 +504,14 @@ on the naive implementation.
When performing matching, implementations are allowed
to treat the following functions and methods as pure:

For any class supporting ``MATCH_SEQUENCE`` or ``MATCH_MAPPING``::
For any class supporting ``MATCH_SEQUENCE``::

* ``cls.__len__()``
* ``cls.__getitem__()``

For any class supporting ``MATCH_MAPPING``::

* ``cls.keys()``
* ``cls.__contains__()``
* ``cls.get()`` (Two argument form only)

Implementations are allowed to make the following assumptions:

Expand All @@ -519,6 +520,8 @@ Implementations are allowed to make the following assumptions:
* Reading any of ``__match_container__``, ``__match_class__`` or ``__match_args__`` is a pure operation, and may be cached.
* Sequences, that is any class for which ``__match_container__&MATCH_SEQUENCE`` is not zero, are not modified by iteration, subscripting or calls to ``len()``.
Consequently, those operations can be freely substituted for each other where they would be equivalent when applied to an immutable sequence.
* Mappings, that is any class for which ``__match_container__&MATCH_MAPPING`` is not zero, will not capture the second argument of the ``get()`` method.
So, the ``$sentinel`` value may be freely re-used.

In fact, implementations are encouraged to make these assumptions, as it is likely to result in signficantly better performance.

Expand Down Expand Up @@ -779,10 +782,14 @@ translates to::
$kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0:
FAIL
if $value.keys() != {"x", "y"}:
$tmp = $value.get("x", $sentinel)
if $tmp is $sentinel:
FAIL
x = $value["x"]
y = $value["y"]
x = $tmp
$tmp = $value.get("y", $sentinel)
if $tmp is $sentinel:
FAIL
y = $tmp
if not x > 2:
FAIL

Expand All @@ -797,9 +804,9 @@ translates to::
$kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0:
FAIL
if not $value.keys() >= {"x", "y"}:
FAIL
$tmp = dict($value)
if not $tmp.keys() >= {"x", "y"}:
FAIL
x = $tmp.pop("x")
y = $tmp.pop("y")
z = $tmp
Expand Down

0 comments on commit c029c02

Please sign in to comment.