        (f)))
   ([f val coll]
      (let [s (seq coll)]
-       (ireduce s f val))))
+       (-reduce s f val))))
 
 (defn reverse
   "Returns a seq of the items in coll in reverse order. Not lazy."


(extend-type goog.global.Array
  ISeqable
  (iseq [array] (array-seq array 0)))

(deftype List [meta first rest count]
  IWithMeta
  (iwith-meta [coll meta] (new List meta first rest count))

  IMeta
  (imeta [coll] meta)

  ISeq
  (ifirst [coll] first)
  (irest [coll] (if (nil? rest) (new EmptyList meta) rest))

  IStack
  (ipeek [coll] first)
  (ipop [coll] (irest coll))

  ICollection
  (iconj [coll o] (new List meta o coll (inc count)))

; IEmptyableCollection
; (iempty [coll] coll)

  ISeqable
  (iseq [coll] coll)

  ICounted
  (icount [coll] count))

(deftype EmptyList [meta]
  IWithMeta
  (iwith-meta [coll meta] (new EmptyList meta))

  IMeta
  (imeta [coll] meta)

  ISeq
  (ifirst [coll] nil)
  (irest [coll] nil)

  IStack
  (ipeek [coll] nil)
  (ipop [coll] #_(throw "Can't pop empty list"))

  ICollection
  (iconj [coll o] (new List meta o nil 1))

; IEmptyableCollection
; (iempty [coll] coll)

  ISeqable
  (iseq [coll] nil)

  ICounted
  (icount [coll] 0))

(set! cljs.core.List.EMPTY (new EmptyList nil))


  that implement Iterable."
  [coll]
  (when coll
    (-seq coll)))

(defn first
  "Returns the first item in the collection. Calls seq on its
  argument. If coll is nil, returns nil."
  [coll]
  (when coll
    (-first (seq coll))))

(defn rest
  "Returns a possibly empty seq of the items after the first. Calls seq on its
  argument."
  [coll]
  (when coll
    (-rest (seq coll))))

(defn next
  "Returns a seq of the items after the first. Calls seq on its
