diff --git a/hy/contrib/dispatch/__init__.py b/hy/contrib/dispatch/__init__.py deleted file mode 100644 index a14091b..0000000 --- a/hy/contrib/dispatch/__init__.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Decorator for defmulti -# -# Copyright (c) 2014 Morten Linderud -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from collections import defaultdict - - -class MultiDispatch(object): - _fns = defaultdict(dict) - - def __init__(self, fn): - self.fn = fn - self.__doc__ = fn.__doc__ - if fn.__name__ not in self._fns[fn.__module__].keys(): - self._fns[fn.__module__][fn.__name__] = {} - values = fn.__code__.co_varnames - self._fns[fn.__module__][fn.__name__][values] = fn - - def is_fn(self, v, args, kwargs): - """Compare the given (checked fn) too the called fn""" - com = list(args) + list(kwargs.keys()) - if len(com) == len(v): - return all([kw in com for kw in kwargs.keys()]) - return False - - def __call__(self, *args, **kwargs): - for i, fn in self._fns[self.fn.__module__][self.fn.__name__].items(): - if self.is_fn(i, args, kwargs): - return fn(*args, **kwargs) - raise TypeError("No matching functions with this signature!") diff --git a/hy/contrib/multi.hy b/hy/contrib/multi.hy index f8216f6..d79ae2e 100644 --- a/hy/contrib/multi.hy +++ b/hy/contrib/multi.hy @@ -25,6 +25,35 @@ [hy.models.list [HyList]] [hy.models.string [HyString]]) +(defclass MultiDispatch [object] [ + + _fns (defaultdict dict) + + __init__ (fn [self f] + (setv self.f f) + (setv self.__doc__ f.__doc__) + (unless (in f.__name__ (.keys (get self._fns f.__module__))) + (setv (get self._fns f.__module__ f.__name__) {})) + (setv values f.__code__.co_varnames) + (setv (get self._fns f.__module__ f.__name__ values) f)) + + fn? (fn [self v args kwargs] + "Compare the given (checked fn) to the called fn" + (setv com (+ (list args) (list (.keys kwargs)))) + (and + (= (len com) (len v)) + (.issubset (frozenset (.keys kwargs)) com))) + + __call__ (fn [self &rest args &kwargs kwargs] + (setv output None) + (for [[i f] (.items (get self._fns self.f.__module__ self.f.__name__))] + (when (.fn? self i args kwargs) + (setv output (apply f args kwargs)) + (break))) + (if output + output + (raise (TypeError "No matching functions with this signature"))))]) + (defn multi-decorator [dispatch-fn] (setv inner (fn [&rest args &kwargs kwargs] (setv dispatch-key (apply dispatch-fn args kwargs)) @@ -73,7 +102,7 @@ (do (def comment (car bodies)) (def bodies (cdr bodies)))) (def ret `(do)) - (.append ret '(import [hy.contrib.dispatch [MultiDispatch]])) + (.append ret '(import [hy.contrib.multi [MultiDispatch]])) (for [body bodies] (def let-binds (car body)) (def body (cdr body))