From ad59fd7ff65b13bcc8ecf5767f66a90735dab582 Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Mon, 19 Mar 2018 17:40:10 -0400 Subject: [PATCH] In -> and ->>, don't modify the arguments --- NEWS.rst | 1 + hy/core/macros.hy | 22 ++++++++++------------ tests/native_tests/language.hy | 12 ++++++++++++ tests/resources/macros.hy | 9 +++++++++ 4 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 tests/resources/macros.hy diff --git a/NEWS.rst b/NEWS.rst index 311fd9a..def307c 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -25,6 +25,7 @@ New Features Bug Fixes ------------------------------ * Fix `(return)` so it works correctly to exit a Python 2 generator +* Fixed a case where `->` and `->>` duplicated an argument Misc. Improvements ---------------------------- diff --git a/hy/core/macros.hy b/hy/core/macros.hy index e478098..34956bb 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -142,17 +142,16 @@ in order of the given pairs." (_for 'for/a* args body)) -(defmacro -> [head &rest rest] +(defmacro -> [head &rest args] "Thread `head` first through the `rest` of the forms. The result of the first threaded form is inserted into the first position of the second form, the second result is inserted into the third form, and so on." (setv ret head) - (for* [node rest] - (if (not (isinstance node HyExpression)) - (setv node `(~node))) - (.insert node 1 ret) - (setv ret node)) + (for* [node args] + (setv ret (if (isinstance node HyExpression) + `(~(first node) ~ret ~@(rest node)) + `(~node ~ret)))) ret) @@ -168,17 +167,16 @@ the second form, the second result is inserted into the third form, and so on." ~@(map build-form expressions) ~f)) -(defmacro ->> [head &rest rest] +(defmacro ->> [head &rest args] "Thread `head` last through the `rest` of the forms. The result of the first threaded form is inserted into the last position of the second form, the second result is inserted into the third form, and so on." (setv ret head) - (for* [node rest] - (if (not (isinstance node HyExpression)) - (setv node `(~node))) - (.append node ret) - (setv ret node)) + (for* [node args] + (setv ret (if (isinstance node HyExpression) + `(~@node ~ret) + `(~node ~ret)))) ret) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 8f99b1d..393dfdf 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -742,6 +742,18 @@ (assert (= (.join ", " (* 10 ["foo"])) (->> ["foo"] (* 10) (.join ", "))))) +(defn test-threading-in-macro [] + ; https://github.com/hylang/hy/issues/1537 + ; The macros need to be defined in another file or else the bug + ; isn't visible in cb72a8c155ac4ef8e16afc63ffa80c1d5abb68a7 + (require tests.resources.macros) + + (tests.resources.macros.thread-set-ab) + (assert (= ab 2)) + + (tests.resources.macros.threadtail-set-cd) + (assert (= cd 5))) + (defn test-threading-two [] "NATIVE: test threading macro" diff --git a/tests/resources/macros.hy b/tests/resources/macros.hy new file mode 100644 index 0000000..0f5dcbe --- /dev/null +++ b/tests/resources/macros.hy @@ -0,0 +1,9 @@ +(defmacro thread-set-ab [] + (defn f [&rest args] (.join "" (+ (, "a") args))) + (setv variable (HySymbol (-> "b" (f)))) + `(setv ~variable 2)) + +(defmacro threadtail-set-cd [] + (defn f [&rest args] (.join "" (+ (, "c") args))) + (setv variable (HySymbol (->> "d" (f)))) + `(setv ~variable 5))