clojure - 包含?,conj和recur

时间:2017-05-08 04:13:17

标签: clojure tail-recursion

我正在尝试编写一个带有recur的函数,它会在遇到重复时立即剪切序列([1 2 3 1 4]应该返回[1 2 3]),这是我的函数:

(defn cut-at-repetition [a-seq] 
  (loop[[head & tail] a-seq, coll '()]
    (if (empty? head)
      coll
      (if (contains? coll head)
        coll
        (recur (rest tail) (conj coll head))))))

第一个问题是引发异常的contains?,我尝试用some替换它,但没有成功。第二个问题是recur部分,它也会引发异常

1 个答案:

答案 0 :(得分:0)

我希望听到我为自己撰写的这个效用函数的反馈(使用filter与有状态pred而不是loop):

(defn my-distinct
  "Returns distinct values from a seq, as defined by id-getter."
  [id-getter coll]
  (let [seen-ids (volatile! #{})
        seen?    (fn [id] (if-not (contains? @seen-ids id)
                            (vswap! seen-ids conj id)))]
    (filter (comp seen? id-getter) coll)))

(my-distinct identity "abracadabra")
; (\a \b \r \c \d)

(->> (for [i (range 50)] {:id (mod (* i i) 21) :value i})
     (my-distinct :id)
     pprint)

; ({:id  0, :value 0}
;  {:id  1, :value 1}
;  {:id  4, :value 2}
;  {:id  9, :value 3}
;  {:id 16, :value 4}
;  {:id 15, :value 6}
;  {:id  7, :value 7}
;  {:id 18, :value 9})

filter的文档说" pred必须没有副作用"但我不确定在这种情况下是否可以。 filter是否保证按顺序迭代序列而不是例如向前跳过?