diff --git a/docs/language/api.rst b/docs/language/api.rst index 7a3639c..7e991b3 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -352,6 +352,8 @@ below: Meow +.. _defn: + defn / defun ------------ @@ -422,6 +424,29 @@ Parameters may have following keywords in front of them: => (zig-zag-sum 1 2 3 4 5 6) -3 +.. _defn-alias / defun-alias: + +defn-alias / defun-alias +------------------------ + +.. versionadded:: 0.9.13 + +The `defn-alias` and `defun-alias` macros are much like `defn`_ above, +with the difference 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` and +`defun-alias` have no other differences compared to `defn` and +`defun`. + +.. code-block:: clj + + => (defn-alias [main-name alias] [] + ... (print "Hello!")) + => (main-name) + "Hello!" + => (alias) + "Hello!" + .. _defmacro: defmacro @@ -679,13 +704,16 @@ would thrown a `NameError`. (set-a 5) (print-a) -if --- +if / if-not +----------- the `if` form is used to conditionally select code to be executed. It has to contain the condition block and the block to be executed if the condition evaluates `True`. Optionally it may contain a block that is executed in case -the evaluation of the condition is `False`. +the evaluation of the condition is `False`. The `if-not` form (*new in +0.9.13*) is similar, but the first block after the test will be +executed when the test fails, while the other, conditional one, when +the test succeeds - opposite of the order of the `if` form. Example usage: @@ -695,6 +723,10 @@ Example usage: (print "lets go shopping") (print "lets go and work")) + (if-not (money-left? account) + (print "lets go and work") + (print "lets go shopping")) + Truth values of Python objects are respected. Values `None`, `False`, zero of any numeric type, empty sequence and empty dictionary are considered `False`. Everything else is considered `True`. diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 9219975..ff497b4 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -138,6 +138,13 @@ ret) +(defmacro if-not [test not-branch &optional [yes-branch nil]] + "Like `if`, but execute the first branch when the test fails" + (if (nil? yes-branch) + `(if (not ~test) ~not-branch) + `(if (not ~test) ~not-branch ~yes-branch))) + + (defmacro when [test &rest body] "Execute `body` when `test` is true" `(if ~test (do ~@body))) @@ -145,7 +152,7 @@ (defmacro unless [test &rest body] "Execute `body` when `test` is false" - `(if ~test None (do ~@body))) + `(if-not ~test (do ~@body))) (defmacro yield-from [iterable] @@ -181,3 +188,14 @@ (setv -args (cdr (car -args)))) `(apply ~-fun [~@-args] (dict (sum ~-okwargs []))))) + + +(defmacro-alias [defn-alias defun-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)) diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy index 0841b1e..dc5715d 100644 --- a/tests/native_tests/native_macros.hy +++ b/tests/native_tests/native_macros.hy @@ -176,3 +176,22 @@ (assert (in ":res_" s1)) (assert (in ":res_" s2)) (assert (not (= s1 s2)))) + + +(defn test-if-not [] + (assert (= (if-not True :yes :no) + :no)) + (assert (= (if-not False :yes :no) + :yes)) + (assert (nil? (if-not True :yes))) + (assert (= (if-not False :yes) + :yes))) + + +(defn test-defn-alias [] + (defn-alias [tda-main tda-a1 tda-a2] [] :bazinga) + (defun-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)))