Skip to content

Commit

Permalink
Document overload alternatives.
Browse files Browse the repository at this point in the history
Refs #119.
  • Loading branch information
coady committed May 7, 2024
1 parent a7a395e commit 2372ea6
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,26 @@ for subclass in (float, list, list[float], tuple[int]):
assert not issubclass(subclass, cls)
```

If a type implements a custom `__instancecheck__`, it can opt-in to dispatch (without caching) by registering its metaclass and bases with `subtype.origins`. `parametric` provides a convenient constructor, with support for predicate functions and checking attributes.
If a type implements a custom `__instancecheck__`, it can opt-in to dispatch (without caching) by registering its metaclass and bases with `subtype.origins`. `parametric` provides a convenient constructor, which will match the base class, predicate functions, and check attributes.

```python
from multimethod import parametric

coro = parametric(Callable, asyncio.iscoroutinefunction)
ints = parametric(array, typecode='i')
Coroutine = parametric(Callable, asyncio.iscoroutinefunction)
IntArray = parametric(array, typecode='i')
```

`overload` used to dispatch on annotated predicate functions. It is deprecated because a custom instance check - including using `parametric` - offers the same functionality.
`overload` used to dispatch on annotated predicate functions. It is deprecated because a custom instance check - including using `parametric` - offers the same functionality. Any predicate function can be wrapped with the closest matching base class, including `object` if necessary.

```python
Cls = parametric(object, predicate)
Digits = parametric(str, str.isdigit)
assert isinstance('0', Digits)
assert not isinstance('a', Digits)

@meth.register
def _(arg: Digits): ...
```

### classes
`classmethod` and `staticmethod` may be used with a multimethod, but must be applied _last_, i.e., wrapping the final multimethod definition after all functions are registered. For class and instance methods, `cls` and `self` participate in the dispatch as usual. They may be left blank when using annotations, otherwise use `object` as a placeholder.
Expand Down
27 changes: 24 additions & 3 deletions docs/examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
"metadata": {},
"source": [
"## parametric\n",
"In addition to `issubclass`, multimethods can dispatch on `isinstance` with additional parametric checks."
"In addition to `issubclass`, multimethods can dispatch on `isinstance` with parametric checks."
]
},
{
Expand All @@ -148,7 +148,7 @@
"from concurrent import futures\n",
"from multimethod import parametric\n",
"\n",
"coro = parametric(Callable, asyncio.iscoroutinefunction)\n",
"Coroutine = parametric(Callable, asyncio.iscoroutinefunction)\n",
"\n",
"\n",
"@multimethod\n",
Expand All @@ -157,7 +157,7 @@
"\n",
"\n",
"@multimethod\n",
"async def wait(timeout, func: coro, *args):\n",
"async def wait(timeout, func: Coroutine, *args):\n",
" return await asyncio.wait_for(func(*args), timeout)\n",
"\n",
"\n",
Expand All @@ -173,6 +173,27 @@
"wait(0.5, asyncio.sleep, 0.01)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from array import array\n",
"\n",
"IntArray = parametric(array, typecode='i')\n",
"isinstance(array('i'), IntArray)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"isinstance(array('f'), IntArray)"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down

0 comments on commit 2372ea6

Please sign in to comment.