From daf59a25e4445b8cff6c3765ace5dd02cbbed748 Mon Sep 17 00:00:00 2001
From: Gary Fredericks <fredericksgary@gmail.com>
Date: Thu, 6 Dec 2012 20:20:02 -0600
Subject: [PATCH] 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 57400ef..7931623 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.5.4

