1

I'm trying to figure why this particular function isn't working as expected. I suspect from the error message that it has something to do with the way I'm creating the empty vector for the accumulator.

I have a simple function that returns a sequence of 2-element vectors:

(defn zip-with-index
  "Returns a sequence in which each element is of the
   form [i c] where i is the index of the element and c
   is the element at that index."
   [coll]
   (map-indexed (fn [i c] [i c]) coll))

That works fine. The problem comes when I try to use it in another function

(defn indexes-satisfying
  "Returns a vector containing all indexes of coll that satisfy
   the predicate p."
  [p coll]
  (defn accum-if-satisfies [acc zipped]
    (let [idx (first zipped)
          elem (second zipped)]
      (if (p elem) 
        (conj acc idx)
        (acc))))
  (reduce accum-if-satisfies (vector) (zip-with-index coll)))

It compiles, but when I attempt to use it I get an error:

user=> (indexes-satisfying (partial > 3) [1 3 5 7])
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lang.AFn.throwArity (AFn.java:437)

I can't figure out what's going wrong here. Also if there is a more 'Clojure-like' way of doing what I'm trying to do, I'm interested in hearing about that also.

4

3 回答 3

2

问题可能出在 else 子句上accum-if-satisfies,应该就是accnot (acc)

您可以使用filterandmap而不是reduce. 像那样:

(map #(first %) 
     (filter #(p (second %))
             (zip-with-index coll)))

您也可以调用map-indexedwithvector而不是(fn [i c] [i c])。整个代码看起来像这样:

(defn indexes-satisfying
  [p coll]
  (map #(first %)
       (filter #(p (second %))
               (map-indexed vector coll))))
于 2013-05-09T22:56:18.890 回答
2

至于更类似于 Clojure 的方式,您可以使用

(defn indexes-satisfying [pred coll]
  (filterv #(pred (nth coll %))
           (range (count coll))))

使用filter而不是filterv返回惰性序列而不是向量。

此外,您不应该使用defn来定义内部函数;相反,它将在定义内部函数的命名空间中定义一个全局函数,除此之外还有微妙的副作用。改用letfn

(defn outer [& args]
  (letfn [(inner [& inner-args] ...)]
    (inner ...)))
于 2013-05-09T23:10:14.050 回答
1

另一种方法是:

(defn indexes-satisfying [p coll]
  (keep-indexed #(if (p %2) % nil) coll))
于 2013-05-10T17:09:42.593 回答