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>
* John Patterson <john@johnppatterson.com>
* 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
[ 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)`)

View File

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

View File

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

View File

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