Merge pull request #1349 from woodrush/fix-unquote-splice-none

Allow `unquote-splice` to accept any false value as empty
This commit is contained in:
Kodi Arfer 2017-08-02 19:50:47 -04:00 committed by GitHub
commit e8ffd41202
5 changed files with 28 additions and 12 deletions

View File

@ -77,4 +77,5 @@
* Charles de Lacombe <ealhad@mail.com> * Charles de Lacombe <ealhad@mail.com>
* John Patterson <john@johnppatterson.com> * John Patterson <john@johnppatterson.com>
* Kai Lüke <kailueke@riseup.net> * Kai Lüke <kailueke@riseup.net>
* Neil Lindquist <archer1mail@gmail.com * Neil Lindquist <archer1mail@gmail.com
* Hikaru Ikuta <woodrush924@gmail.com>

1
NEWS
View File

@ -1,6 +1,7 @@
Changes from 0.13.0 Changes from 0.13.0
[ Language Changes ] [ Language Changes ]
* The unquote-splice or ~@ form now accepts any false value as empty.
* `yield-from` is no longer supported under Python 2 * `yield-from` is no longer supported under Python 2
* `apply` has been replaced with Python-style unpacking operators `#*` and * `apply` has been replaced with Python-style unpacking operators `#*` and
`#**` (e.g., `(f #* args #** kwargs)`) `#**` (e.g., `(f #* args #** kwargs)`)

View File

@ -1604,19 +1604,31 @@ unquote-splice
-------------- --------------
``unquote-splice`` forces the evaluation of a symbol within a quasiquoted form, ``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 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 .. code-block:: clj
(def nums [1 2 3 4]) (def nums [1 2 3 4])
(quasiquote (+ (unquote-splice nums))) (quasiquote (+ (unquote-splice nums)))
;=> (u'+' 1L 2L 3L 4L) ;=> ('+' 1 2 3 4)
`(+ ~@nums) `(+ ~@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 when
---- ----

View File

@ -707,7 +707,9 @@ class HyASTCompiler(object):
level) level)
imports.update(f_imports) imports.update(f_imports)
if splice: if splice:
to_add = HyExpression([HySymbol("list"), f_contents]) to_add = HyExpression([
HySymbol("list"),
HyExpression([HySymbol("or"), f_contents, HyList()])])
else: else:
to_add = HyList([f_contents]) to_add = HyList([f_contents])

View File

@ -74,17 +74,17 @@
(defn test-unquote-splice [] (defn test-unquote-splice []
"NATIVE: test splicing unquotes" "NATIVE: test splicing unquotes"
(setv q (quote (c d e))) (setv q (quote (c d e)))
(setv qq (quasiquote (a b (unquote-splice q) f (unquote-splice q)))) (setv qq `(a b ~@q f ~@q ~@0 ~@False ~@None g ~@(when False 1) h))
(assert (= (len qq) 9)) (assert (= (len qq) 11))
(assert (= qq (quote (a b c d e f c d e))))) (assert (= qq (quote (a b c d e f c d e g h)))))
(defn test-nested-quasiquote [] (defn test-nested-quasiquote []
"NATIVE: test nested quasiquotes" "NATIVE: test nested quasiquotes"
(setv qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4))) (setv qq `(1 `~(+ 1 ~(+ 2 3) ~@None) 4))
(setv q (quote (1 (quasiquote (unquote (+ 1 5))) 4))) (setv q (quote (1 `~(+ 1 5) 4)))
(assert (= (len q) 3)) (assert (= (len q) 3))
(assert (= (get qq 1) (quote (quasiquote (unquote (+ 1 5)))))) (assert (= (get qq 1) (quote `~(+ 1 5))))
(assert (= q qq))) (assert (= q qq)))