(defmacro defn [name args body]

'(def ~name (fn ~args ~body)))

(defmacro ->> [coll &forms]

(.reduce forms coll (fn [a f] (.<< f a))))

(defmacro -> [coll &forms]

(.reduce forms coll
         (fn [a f]
           (.concat '(~(first f) ~a) (rest f)))))

(defn + [&xs]

(.reduce xs 0 :+))

(defn - [x &xs]

(if (.empty? xs)
  (- 0 x)
  (.reduce xs x :-)))

(defn * [&xs]

(.reduce xs 1 :*))

(defn / [x &xs]

(if (.empty? xs)
  (/ 1 x)
  (.reduce xs x :/)))

(defn > [&xs]

(.all? (.each_cons xs 2) (fn [[a b]] (.> a b))))

(defn >= [&xs]

(.all? (.each_cons xs 2) (fn [[a b]] (.>= a b))))

(defn < [&xs]

(.all? (.each_cons xs 2) (fn [[a b]] (.< a b))))

(defn <= [&xs]

(.all? (.each_cons xs 2) (fn [[a b]] (.<= a b))))

(defn = [&xs]

(.all? (.each_cons xs 2) (fn [[a b]] (.== a b))))

(defn compare [a b]

(.<=> a b))

(defn vector [&xs]

(.new Hamster/Vector xs))

(defn set [&xs]

(.new Hamster/Set xs))

(defn sorted-set [&xs]

(.new Hamster/SortedSet xs))

(defn sorted-set-by [comparator &xs]

(.new Hamster/SortedSet xs comparator))

(defn list [&xs]

(.new Hamster/List xs))

(defn hash-map [&xs]

(.new Hamster/Hash (.each_slice xs 2)))

(defn ruby-array [&xs]

(.new Array xs))

(defn ruby-set [&xs]

(.new Set xs))

(defn ruby-hash [&xs]

(.to_h (.each_slice xs 2)))

(defn nil? [x]

(.nil? x))

(defn filter [f coll]

(.select coll f))

(defn map [f coll]

(.map coll f))

(defn reduce [f s coll]

(if (nil? coll)
  (.reduce s f)
  (.reduce coll s f)))

(defn take [n coll]

(.take coll n))

(defn drop [n coll]

(.drop coll n))

(defn first [coll]

(.first coll))

(defn rest [coll]

(drop 1 coll))

(defn get [coll k default]

(.fetch coll k default))

(defn println [&xs]

(.puts (.new Object) (.join xs " ")))