Mark Karpov
Mark Karpov

Reputation: 7599

Difference between "->" and "->>" in Clojure

What's difference between macros -> and ->>:

user> (macroexpand-1 '(->> 1 a b c))
;; => (c (b (a 1)))
user> (macroexpand-1 '(-> 1 a b c))
;; => (c (b (a 1)))

Let's see source code:

user> (clojure.repl/source ->)
(defmacro ->
  "Threads the expr through the forms. Inserts x as the
  second 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
  second item in second form, etc."
  {:added "1.0"}
  [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)))
;; => nil

user> (clojure.repl/source ->>)
(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 & 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))]
        (recur threaded (next forms)))
      x)))
;; => nil

(Indentation is mine.)

So, -> is older, but they look pretty the same... Any reason for duplication?

Upvotes: 0

Views: 208

Answers (1)

C. K. Young
C. K. Young

Reputation: 223023

The two macros are different when dealing with threaded forms that take further arguments. Try these for size:

(macroexpand '(->> 1 (a b) (c d e) (f g h i)))
(macroexpand '(-> 1 (a b) (c d e) (f g h i)))

Upvotes: 3

Related Questions