From a0224ef8bdbbcafbd4d8ec8be7454247f703c16c Mon Sep 17 00:00:00 2001 From: Hikaru Ikuta Date: Wed, 2 Aug 2017 00:50:37 +0900 Subject: [PATCH 1/3] Allow `unquote-splice` to accept any false value as empty --- NEWS | 1 + hy/compiler.py | 4 +++- tests/native_tests/quote.hy | 12 ++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 2c52152..338c7e6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ Changes from 0.13.0 [ Language Changes ] + * The unquote-splice or ~@ form now accepts any false value as empty. * `yield-from` is no longer supported under Python 2 * `apply` has been replaced with Python-style unpacking operators `#*` and `#**` (e.g., `(f #* args #** kwargs)`) diff --git a/hy/compiler.py b/hy/compiler.py index 5fd073f..a0f3589 100755 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -707,7 +707,9 @@ class HyASTCompiler(object): level) imports.update(f_imports) if splice: - to_add = HyExpression([HySymbol("list"), f_contents]) + to_add = HyExpression([ + HySymbol("list"), + HyExpression([HySymbol("or"), f_contents, HyList()])]) else: to_add = HyList([f_contents]) diff --git a/tests/native_tests/quote.hy b/tests/native_tests/quote.hy index 32a11b9..e1c9f3b 100644 --- a/tests/native_tests/quote.hy +++ b/tests/native_tests/quote.hy @@ -74,17 +74,17 @@ (defn test-unquote-splice [] "NATIVE: test splicing unquotes" (setv q (quote (c d e))) - (setv qq (quasiquote (a b (unquote-splice q) f (unquote-splice q)))) - (assert (= (len qq) 9)) - (assert (= qq (quote (a b c d e f c d e))))) + (setv qq `(a b ~@q f ~@q ~@0 ~@False ~@None g ~@(when False 1) h)) + (assert (= (len qq) 11)) + (assert (= qq (quote (a b c d e f c d e g h))))) (defn test-nested-quasiquote [] "NATIVE: test nested quasiquotes" - (setv qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4))) - (setv q (quote (1 (quasiquote (unquote (+ 1 5))) 4))) + (setv qq `(1 `~(+ 1 ~(+ 2 3) ~@None) 4)) + (setv q (quote (1 `~(+ 1 5) 4))) (assert (= (len q) 3)) - (assert (= (get qq 1) (quote (quasiquote (unquote (+ 1 5)))))) + (assert (= (get qq 1) (quote `~(+ 1 5)))) (assert (= q qq))) From dbffe987f5dae83e398794c418b1f1ccc3b38375 Mon Sep 17 00:00:00 2001 From: Hikaru Ikuta Date: Wed, 2 Aug 2017 00:51:19 +0900 Subject: [PATCH 2/3] Update docs on `unquote-splice` --- docs/language/api.rst | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/language/api.rst b/docs/language/api.rst index 3904e86..88da5d3 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -1604,19 +1604,31 @@ unquote-splice -------------- ``unquote-splice`` forces the evaluation of a symbol within a quasiquoted form, -much like ``unquote``. ``unquote-splice`` can only be used when the symbol +much like ``unquote``. ``unquote-splice`` can be used when the symbol being unquoted contains an iterable value, as it "splices" that iterable into -the quasiquoted form. ``unquote-splice`` is aliased to the ``~@`` symbol. +the quasiquoted form. ``unquote-splice`` can also be used when the value +evaluates to a false value such as ``None``, ``False``, or ``0``, in which +case the value is treated as an empty list and thus does not splice anything +into the form. ``unquote-splice`` is aliased to the ``~@`` syntax. .. code-block:: clj (def nums [1 2 3 4]) (quasiquote (+ (unquote-splice nums))) - ;=> (u'+' 1L 2L 3L 4L) + ;=> ('+' 1 2 3 4) `(+ ~@nums) - ;=> (u'+' 1L 2L 3L 4L) + ;=> ('+' 1 2 3 4) + `[1 2 ~@(if (< (nth nums 0) 0) nums)] + ;=> ('+' 1 2) + +Here, the last example evaluates to ``('+' 1 2)``, since the condition +``(< (nth nums 0) 0)`` is ``False``, which makes this ``if`` expression +evaluate to ``None``, because the ``if`` expression here does not have an +else clause. ``unquote-splice`` then evaluates this as an empty value, +leaving no effects on the list it is enclosed in, therefore resulting in +``('+' 1 2)``. when ---- From c8ce998a3f808e8493b30ad103696d6081f16947 Mon Sep 17 00:00:00 2001 From: Hikaru Ikuta Date: Wed, 2 Aug 2017 00:51:44 +0900 Subject: [PATCH 3/3] Add Hikaru Ikuta to AUTHORS --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 84e2a1d..2c1f274 100644 --- a/AUTHORS +++ b/AUTHORS @@ -77,4 +77,5 @@ * Charles de Lacombe * John Patterson * Kai Lüke -* Neil Lindquist \ No newline at end of file