From a77361f5333b09b53adeb3b43959a9b904ed63ad Mon Sep 17 00:00:00 2001
From: Gary Fredericks <fredericksgary@gmail.com>
Date: Thu, 6 Dec 2012 20:20:02 -0600
Subject: [PATCH 1/2] CLJ-1121 Reimplement -> and ->> without recursion

The recursive definitions can be subtly dependent on the behavior
of macros in the forms passed to them.
---
 src/clj/clojure/core.clj             |   27 ++++++++++++++++++---------
 test/clojure/test_clojure/macros.clj |   18 ++++++++++++++++++
 2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 1b72090..0f0ab4c 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1548,22 +1548,31 @@
   list already. If there are more forms, inserts the first form as the
   second item in second form, etc."
   {:added "1.0"}
-  ([x] x)
-  ([x form] (if (seq? form)
-              (with-meta `(~(first form) ~x ~@(next form)) (meta form))
-              (list form x)))
-  ([x form & more] `(-> (-> ~x ~form) ~@more)))
+  [x & forms]
+  (loop [x x, forms forms]
+    (if forms
+      (let [form (first forms)
+            threaded (if (seq? form)
+                       (with-meta `(~(first form) ~x ~@(next form)) (meta form))
+                       (list form x))]
+        (recur threaded (next forms)))
+      x)))
 
 (defmacro ->>
   "Threads the expr through the forms. Inserts x as the
   last item in the first form, making a list of it if it is not a
   list already. If there are more forms, inserts the first form as the
   last item in second form, etc."
-  {:added "1.1"} 
-  ([x form] (if (seq? form)
+  {:added "1.1"}
+  [x & forms]
+  (loop [x x, forms forms]
+    (if forms
+      (let [form (first forms)
+            threaded (if (seq? form)
               (with-meta `(~(first form) ~@(next form)  ~x) (meta form))
-              (list form x)))
-  ([x form & more] `(->> (->> ~x ~form) ~@more)))
+              (list form x))]
+        (recur threaded (next forms)))
+      x)))
 
 (def map)
 
diff --git a/test/clojure/test_clojure/macros.clj b/test/clojure/test_clojure/macros.clj
index 711130e..72fd377 100644
--- a/test/clojure/test_clojure/macros.clj
+++ b/test/clojure/test_clojure/macros.clj
@@ -16,3 +16,21 @@
 ; ->
 ; defmacro definline macroexpand-1 macroexpand
 
+
+;; -> and ->> should not be dependent on the meaning of their arguments
+
+(defmacro c
+  [arg]
+  (if (= 'b (first arg))
+    :foo
+    :bar))
+
+(deftest ->test
+  (let [a 2, b identity]
+    (is (= (-> a b c)
+           (c (b a))))))
+
+(deftest ->>test
+  (let [a 2, b identity]
+    (is (= (->> a b c)
+           (c (b a))))))
\ No newline at end of file
-- 
1.7.9.5


From 8076f8ba7fe68bfb750956c2782c945dc83f1dad Mon Sep 17 00:00:00 2001
From: Gary Fredericks <fredericksgary@gmail.com>
Date: Wed, 26 Dec 2012 19:47:58 -0600
Subject: [PATCH 2/2] CLJ-1121 Add metadata tests for -> and ->>

---
 test/clojure/test_clojure/macros.clj |   35 +++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/test/clojure/test_clojure/macros.clj b/test/clojure/test_clojure/macros.clj
index 72fd377..e832b7e 100644
--- a/test/clojure/test_clojure/macros.clj
+++ b/test/clojure/test_clojure/macros.clj
@@ -33,4 +33,37 @@
 (deftest ->>test
   (let [a 2, b identity]
     (is (= (->> a b c)
-           (c (b a))))))
\ No newline at end of file
+           (c (b a))))))
+
+(deftest ->metadata-test
+  (testing "a trivial form"
+    (is (= {:hardy :har :har :-D}
+           (meta (macroexpand-1 (list `-> (with-meta
+                                            'quoted-symbol
+                                            {:hardy :har :har :-D})))))))
+  (testing "a nontrivial form"
+    (let [a (with-meta 'a {:foo :bar})
+          b (with-meta '(b c d) {:bar :baz})
+          e (with-meta 'e {:baz :quux})
+          expanded (macroexpand-1 (list `-> a b e))]
+      (is (= expanded '(e (b a c d))))
+      (is (= {:baz :quux} (meta (first expanded))))
+      (is (= {:bar :baz} (meta (second expanded))))
+      (is (= {:foo :bar} (meta (second (second expanded))))))))
+
+
+(deftest ->>metadata-test
+  (testing "a trivial form"
+    (is (= {:hardy :har :har :-D}
+           (meta (macroexpand-1 (list `->> (with-meta
+                                             'quoted-symbol
+                                             {:hardy :har :har :-D})))))))
+  (testing "a non-trivial form"
+    (let [a (with-meta 'a {:foo :bar})
+          b (with-meta '(b c d) {:bar :baz})
+          e (with-meta 'e {:baz :quux})
+          expanded (macroexpand-1 (list `->> a b e))]
+      (is (= expanded '(e (b c d a))))
+      (is (= {:baz :quux} (meta (first expanded))))
+      (is (= {:bar :baz} (meta (second expanded))))
+      (is (= {:foo :bar} (meta (last (second expanded))))))))
-- 
1.7.9.5

