Merge branch 'contrib-cleanup'

This commit is contained in:
Kodi Arfer 2016-12-30 08:06:59 -08:00
commit 9449584c7f
22 changed files with 53 additions and 374 deletions

View File

@ -1,60 +0,0 @@
============
Alias macros
============
.. versionadded:: 0.12
The alias macro module provides the ``(defn-alias)`` and
``(defmacro-alias)``, that were in Hy core previously.
Macros
======
.. _defn-alias:
defn-alias
------------------------
The ``defn-alias`` macro is much like ``defn``,
with the distinction that instead of defining a function with a single
name, these can also define aliases. Other than taking a list of
symbols for function names as the first parameter, ``defn-alias``
is no different from ``defn``.
.. code-block:: clj
=> (defn-alias [main-name alias] []
... (print "Hello!"))
=> (main-name)
"Hello!"
=> (alias)
"Hello!"
.. _defmacro-alias:
defmacro-alias
--------------
``defmacro-alias`` is used to define macros with multiple names
(aliases). The general format is ``(defmacro-alias [names] [parameters]
expr)``. It creates multiple macros with the same parameter list and
body, under the specified list of names.
The following example defines two macros, both of which allow the user
to write code in infix notation.
.. code-block:: clj
=> (defmacro-alias [infix infi] [code]
... (quasiquote (
... (unquote (get code 1))
... (unquote (get code 0))
... (unquote (get code 2)))))
=> (infix (1 + 1))
2
=> (infi (1 + 1))
2

View File

@ -1,58 +0,0 @@
==========
Flow
==========
.. versionadded:: 0.10.1
The ``flow`` macros allow directing the flow of a program with greater ease.
Macros
======
.. _case:
.. _switch:
case
-----
``case`` allows you to decide based on the value of a variable.
Usage: `(case variable val1 (body1) val2 (body2) ...)`
Example:
.. code-block:: hy
(require [hy.contrib.flow [case]])
(defn temp-commenter [temp]
(case temp
-10 (print "It's freezing. Turn up the thermostat!")
15 (print "Sounds about average.")
45 (print "Holy smokes. It's hot in here!")
(print "I don't even know.")))
switch
-----
``switch`` allows you to run code based on the value of a variable.
A final extra body allows for a default case.
Usage: `(switch var (cond1) (body1) (cond2) (body2) ... )`
Example:
.. code-block:: hy
(require [hy.contrib.flow [switch]])
(defn temp-commenter [temp]
(switch temp
(<= 10.0) (print "Better wear a jacket!")
(<= 25.0) (print "Brace yourselves. Summer is coming!")
(<= 30.0) (print "Time to get some ice cream.")
(print "Sounds like a heat wave")))

View File

@ -2,14 +2,15 @@
Contributor Modules Index
=========================
These modules are experimental additions to Hy. Once deemed mature,
they will be moved to the ``hy.extra`` namespace or loaded by
default.
Contents:
.. toctree::
:maxdepth: 3
alias
anaphoric
flow
loop
multi
profile

View File

@ -13,9 +13,9 @@ concise and easy to read.
-- Wikipedia (https://en.wikipedia.org/wiki/Anaphoric_macro)
To use these macros you need to require the hy.contrib.anaphoric module like so:
To use these macros you need to require the ``hy.extra.anaphoric`` module like so:
``(require [hy.contrib.anaphoric [*]])``
``(require [hy.extra.anaphoric [*]])``
.. _ap-if:

14
docs/extra/index.rst Normal file
View File

@ -0,0 +1,14 @@
===================
Extra Modules Index
===================
These modules are considered no less stable than Hy's built-in
functions and macros, but they need to be loaded with ``(import
...)`` or ``(require ...)``.
Contents:
.. toctree::
:maxdepth: 3
anaphoric

View File

@ -34,5 +34,6 @@ Contents:
tutorial
style-guide
language/index
extra/index
contrib/index
hacking

View File

@ -1,39 +0,0 @@
;; Copyright (c) 2014, 2015 Gergely Nagy
;; Copyright (c) 2014, 2015 Paul Tagliamonte <paultag@debian.org>
;; 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.
(defmacro defmacro-alias [names lambda-list &rest body]
"define one macro with several names"
(setv ret `(do))
(for* [name names]
(.append ret
`(defmacro ~name ~lambda-list ~@body)))
ret)
(defmacro defn-alias [names lambda-list &rest body]
"define one function with several names"
(let [main (first names)
aliases (rest names)]
(setv ret `(do (defn ~main ~lambda-list ~@body)))
(for* [name aliases]
(.append ret
`(setv ~name ~main)))
ret))

View File

@ -1,21 +0,0 @@
(import inspect functools sys)
(defn curry [func]
(let [sig (.getargspec inspect func)
count (len sig.args)]
(fn [&rest args]
(if (< (len args) count)
(apply functools.partial (+ [(curry func)] (list args)))
(apply func args)))))
(defmacro fnc [args &rest body]
`(do (import hy.contrib.curry)
(with-decorator hy.contrib.curry.curry (fn [~@args] ~@body))))
(defmacro defnc [name args &rest body]
`(do (require hy.contrib.curry)
(def ~name (hy.contrib.curry.fnc [~@args] ~@body))))

View File

@ -1,50 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Decorator for defmulti
#
# Copyright (c) 2014 Morten Linderud <mcfoxax@gmail.com>
#
# 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!")

View File

@ -1,24 +0,0 @@
;; Additional flow macros
(defmacro/g! switch [variable &rest args]
(setv g!comp (car args))
(setv g!body (car (cdr args)))
(setv g!rest (cdr (cdr args)))
(setv g!cond `(~(car g!comp) ~variable ~@(cdr g!comp)))
(if g!rest
(if (cdr g!rest)
`(if ~g!cond ~g!body (switch ~variable ~@g!rest))
`(if ~g!cond ~g!body ~@g!rest))
`(if ~g!cond ~g!body)))
(defmacro/g! case [variable &rest args]
(setv g!value (car args))
(setv g!body (car (cdr args)))
(setv g!rest (cdr (cdr args)))
(setv g!cond `(= ~variable ~g!value))
(if g!rest
(if (cdr g!rest)
`(if ~g!cond ~g!body (case ~variable ~@g!rest))
`(if ~g!cond ~g!body ~@g!rest))
`(if ~g!cond ~g!body)))

View File

@ -1,31 +0,0 @@
;;; Hy on Meth
;;; based on paultag's meth library to access a Flask based application
(defmacro route-with-methods [name path methods params &rest code]
"Same as route but with an extra methods array to specify HTTP methods"
`(let [deco (apply app.route [~path]
{"methods" ~methods})]
(with-decorator deco
(defn ~name ~params
(do ~@code)))))
(defn rwm [name path method params code]
`(do (require hy.contrib.meth)
(hy.contrib.meth.route-with-methods ~name ~path ~method ~params ~@code)))
;; Some macro examples
(defmacro route [name path params &rest code]
"Get request"
(rwm name path ["GET"] params code))
(defmacro post-route [name path params &rest code]
"Post request"
(rwm name path ["POST"] params code))
(defmacro put-route [name path params &rest code]
"Put request"
(rwm name path ["PUT"] params code))
(defmacro delete-route [name path params &rest code]
"Delete request"
(rwm name path ["DELETE"] params code))

View File

@ -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))

0
hy/extra/__init__.py Normal file
View File

View File

@ -1,5 +1,3 @@
# for Botsbuildbots
requests
# code quality
flake8
coverage

View File

@ -14,13 +14,10 @@ from .native_tests.core import * # noqa
from .native_tests.reader_macros import * # noqa
from .native_tests.shadow import * # noqa
from .native_tests.with_test import * # noqa
from .native_tests.contrib.anaphoric import * # noqa
from .native_tests.extra.anaphoric import * # noqa
from .native_tests.contrib.loop import * # noqa
from .native_tests.contrib.meth import * # noqa
from .native_tests.contrib.walk import * # noqa
from .native_tests.contrib.multi import * # noqa
from .native_tests.contrib.curry import * # noqa
from .native_tests.contrib.botsbuildbots import * # noqa
from .native_tests.contrib.sequences import * # noqa
if PY3:

View File

@ -1,8 +0,0 @@
(require [hy.contrib.alias [defn-alias]])
(defn test-defn-alias []
(defn-alias [tda-main tda-a1 tda-a2] [] :bazinga)
(assert (= (tda-main) :bazinga))
(assert (= (tda-a1) :bazinga))
(assert (= (tda-a2) :bazinga))
(assert (= tda-main tda-a1 tda-a2)))

View File

@ -1,4 +0,0 @@
(require [hy.contrib.botsbuildbots [Botsbuildbots]])
(defn test-botsbuildbots []
(assert (> (len (first (Botsbuildbots))) 50)))

View File

@ -1,13 +0,0 @@
(require [hy.contrib.curry [defnc]])
(defnc s [x y z] ((x z) (y z))) ; λxyz.xz(yz)
(defnc k [x] (fn [y] x)) ; λx.λy.x
(defnc i [x] x) ;; λx.x
(defnc succ [n] (+ n 1))
(defn test-curry []
(assert (= 16 (((((s ((((k s) k) i) i)) (i i)) ((i (i i))
((((k s) i) ((s (k s)) k)) i))) succ) 0))))

View File

@ -1,53 +0,0 @@
(require [hy.contrib.meth [route post-route put-route delete-route]])
(defclass FakeMeth []
"Mocking decorator class"
[rules {}]
(defn route [self rule &kwargs options]
(fn [f]
(assoc self.rules rule (, f options))
f)))
(defn test_route []
(let [app (FakeMeth)]
(route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "GET" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_post_route []
(let [app (FakeMeth)]
(post-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "POST" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_put_route []
(let [app (FakeMeth)]
(put-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "PUT" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))
(defn test_delete_route []
(let [app (FakeMeth)]
(delete-route get-index "/" [] (str "Hy world!"))
(setv app-rules (getattr app "rules"))
(assert (in "/" app-rules))
(let [(, rule-fun rule-opt) (get app-rules "/")]
(assert (not (empty? rule-opt)))
(assert (in "DELETE" (get rule-opt "methods")))
(assert (= (getattr rule-fun "__name__") "get_index"))
(assert (= "Hy world!" (rule-fun))))))

View File

View File

@ -19,7 +19,7 @@
;; DEALINGS IN THE SOFTWARE.
(import [hy.errors [HyMacroExpansionError]])
(require [hy.contrib.anaphoric [*]])
(require [hy.extra.anaphoric [*]])
;;;; some simple helpers