Matching module¶
The Match module¶
This module implements a technique for pattern matching.
IDEA: Statement-oriented matcher within the same scope: with ValueMatcher(‘sum’, 1, 2, 3) as m:
High-level functions¶
-
kingston.match.
matches
(values: Sequence[T_co], patterns: Sequence[T_co], matchfn: Callable = <function match>) → Sequence[T_co][source]¶ Tries to match
values
frompatterns
.Parameters: - values – A sequence of values to match.
- patterns – A sequence of patterns that may match
values
.
Returns: The pattern that was matched or
Miss
.Return type: Union[Sequence, Type[Miss]]
High-level classes¶
-
class
kingston.match.
Matcher
[source]¶ Common base for all matcher classes.
Since
Matcher
is alsoGeneric
, you use it to subtype concrete instances of matchers you implement.
-
class
kingston.match.
TypeMatcher
[source]¶ Concrete implementation of a type matcher instance.
If you want to type a type matcher, use standard technique when using
Generic
types:>>> from kingston.match import Matcher, TypeMatcher >>> my_int_matcher:Matcher[int, int] = TypeMatcher({ ... int: lambda x: x+1, ... str: lambda x: 'str'}) >>> my_int_matcher(10) 11 >>> my_int_matcher(20) 21 >>> my_int_matcher('foo') # ok at runtime but fails mypy 'str' >>>
It will try to give a reasonably human representation when inspected:
>>> my_int_matcher <TypeMatcher: (int)->λ, (str)->λ > >>>
You can also subclass type matchers and use a decorator to declare cases as methods:
>>> from kingston.match import Matcher, TypeMatcher, case >>> from numbers import Number >>> class NumberDescriber(TypeMatcher): ... @case ... def describe_one_int(self, one:int) -> str: ... return "One integer" ... ... @case ... def describe_two_ints(self, one:int, two:int) -> str: ... return "Two integers" ... ... @case ... def describe_one_float(self, one:float) -> str: ... return "One float" >>> my_num_matcher:Matcher[Number, str] = NumberDescriber() >>> my_num_matcher(1) 'One integer' >>> my_num_matcher(1, 2) 'Two integers' >>> my_num_matcher(1.0) 'One float' >>>
-
class
kingston.match.
ValueMatcher
[source]¶ Concrete implementation of a value matching instance.
If you want to type a type matcher, use standard technique when using
Generic
types:>>> from kingston.match import ValueMatcher, Miss >>> my_val_matcher:Matcher[int, str] = ValueMatcher({ ... 1: lambda x: 'one!', ... 2: lambda x: 'two!', ... Miss: lambda x: 'many!'}) >>> my_val_matcher(1) 'one!' >>> my_val_matcher(2) 'two!' >>> my_val_matcher(3) 'many!' >>> my_val_matcher('x') # ok at runtime but fails mypy (& missleading..) 'many!' >>>
It will try to give a reasonably human representation when inspected:
>>> my_val_matcher <ValueMatcher: (1)->λ, (2)->λ, (<class 'kingston.match.Miss_'>)->λ > >>>
You can also declare cases as methods in a custom
ValueMatcher
subclass.Use the function
value_case()
to declare value cases. Note: imported as a shorthand:>>> from kingston.match import Matcher, ValueMatcher >>> from kingston.match import value_case as case >>> class SimplestEval(ValueMatcher): ... @case(Any, '+', Any) ... def _add(self, a, op, b) -> int: ... return a + b ... ... @case(Any, '-', Any) ... def _sub(self, a, op, b) -> int: ... return a - b >>> simpl_eval = SimplestEval() >>> simpl_eval(1, '+', 2) 3 >>> simpl_eval(10, '-', 5) 5
Exceptions and symbols¶
-
exception
kingston.match.
Conflict
[source]¶ Exception raised if a pattern to be matched already have been applied to a Matcher instance.
-
kingston.match.
Miss
¶