coady / multimethod

Multiple argument dispatching.
https://coady.github.io/multimethod
Other
277 stars 24 forks source link

multimethod dispatch on typing.Literal #44

Closed adam-urbanczyk closed 3 years ago

adam-urbanczyk commented 3 years ago

Would it be possible to implement multimethods dispatching on typing.Literal?

coady commented 3 years ago

I don't think so. The dispatch - and moreover the caching - relies on issubclass. Anything that would make the dispatch as slow as a linear scan would probably be better as part of overload, which already does that. It only supports predicate functions at the moment, but that could be extended.

Another workaround is to use an enum.

adam-urbanczyk commented 3 years ago

Thanks, I'm aware that enum would work but it is not a part of the current API of the module I'm trying to use multimethod with. Would it (almost) work with a custom Literal type implementing __subclasshook__? I assume that you could cache the resolutions based on the args of the Literal - for all practical uses I have seen either str or numbers.

FYI: what I would like to achieve in the end is dispatching based on typing annotations including Literal.

coady commented 3 years ago

Would it work for your use case to partially support Literal, i.e., still be subclass based.

Literal['a', 'b']) -> str
Literal['a', 0]) -> Union[str, int]
Literal['a', None]) -> Optional[str]

It wouldn't check the values, but it would allow a Literal annotation to be present, with a sanity check.

adam-urbanczyk commented 3 years ago

I think that would work! I have this kind of signatures:

 def constrain(self, tag: str, constraint: Literal['a','b','c'], arg: Any)

and

 def constrain(self, tag1: str, tag2: str, constraint: Literal['a','b','c'], arg: Any)
adam-urbanczyk commented 3 years ago

Thanks @coady !