From ca8b6b4fe5ba3dfb85058cb502b907a944685f55 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Sun, 2 Aug 2015 23:57:46 +0300 Subject: [PATCH] Add exclusive or logical operator Added xor to complement and, or, not operators. Standard python falsey/truthy semantics are followed. This implementation works for two or more parameters. --- docs/language/api.rst | 22 ++++++++++++++++++++++ hy/core/macros.hy | 5 +++++ tests/native_tests/language.hy | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/docs/language/api.rst b/docs/language/api.rst index 67ef630..ab58065 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -1511,6 +1511,28 @@ expands to: Section :ref:`using-gensym` +xor +--- + +.. versionadded:: 0.12.0 + +``xor`` is used in logical expressions to perform exclusive or. It takes at +least two parameters. It returns ``True`` if exactly one of the parameters +evaluates to ``True``. In all other cases ``False`` is returned. Example +usage: + +.. code-block:: clj + + => (xor True False) + True + + => (xor True True) + False + + => (xor [] [] [0]) + True + + yield ----- diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 014920c..dce89c6 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -237,3 +237,8 @@ (let [[decorators (slice expr nil -1)] [fndef (get expr -1)]] `(with-decorator ~@decorators ~fndef))) + +(defmacro xor [&rest args] + "perform exclusive or comparison between all arguments" + (when (< (len args) 2) (macro-error nil "xor requires at least two arguments.")) + `(= (reduce (fn [a b] (if b (inc a) a)) ~args 0) 1)) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 352ecf5..5ced0cf 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -813,6 +813,23 @@ (assert (= a 1))) +(defn test-xor [] + "NATIVE: test the xor macro" + (let [[xor-both-true (xor true true)] + [xor-both-false (xor false false)] + [xor-true-false (xor true false)] + [xor-one-true (xor false true false)] + [xor-one-false (xor true false true)] + [xor-all-true (xor true true true)] + [xor-all-false (xor false false false)]] + (assert (= xor-both-true false)) + (assert (= xor-both-false false)) + (assert (= xor-true-false true)) + (assert (= xor-one-true true)) + (assert (= xor-one-false false)) + (assert (= xor-all-true false)) + (assert (= xor-all-false false)))) + (defn test-if-return-branching [] "NATIVE: test the if return branching" ; thanks, algernon