2010-11-23 56 views
2

我想实现“缩小地图”功能。也就是说,它应该返回由施加f到第一2项的coll的结果的序列,随后施加f该搜索结果和在coll第三项的结果,等等如何实现懒惰的“缩小地图”功能?

(def c [[0 0 0 0] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]) 

(defn- sum-vector [v1 v2] 
    (map + v1 v2)) 

(defn reduce-map [f coll & acc] 
    (if (< (count coll) 2) 
    (if (empty? acc) coll acc) 
    (let [head (apply f (take 2 coll)) 
      tail (drop 2 coll)] 
     (recur f (conj tail head) (conj acc head))))) 

对于例如,调用这个函数是这样的:

(reduce-map sum-vector c) 

应该返回:

[[1 0 0 0] [1 1 0 0] [1 1 1 0] [1 1 1 1]] 

(实际上,它也许应该返回未修改的第一个项目为好,更好地模拟map,但后来我可以修复)

权,现在,这是它返回:

((1 1 1 1) (1 1 1 0) (1 1 0 0) (1 0 0 0)) 

我如何“推“在(纽约)seq结束?

如果我代替reduce-maprecur,这是它返回:

(((1 1 1 1) ((1 1 1 0) ((1 1 0 0) ((1 0 0 0)))))) 

是在什么上面我的代码recur和真正的递归之间的区别?

而且,是否有内置的,或更好的,或更习惯的方法来实现reduce-map

最后,我想输出序列是懒惰的。我只是将整个东西包装在lazy-seq

回答

10

这听起来有点像reductions

至于在seq末尾的“推”:一般seqs没有“结束”,参见。 (iterate inc 0)

至于在列表的末尾“推”:列表不是为此设计的。使用矢量。用[]播种您的累加器,而不是nil

至于lazy-seq:使用“true”递归而不是recur。这里举一个例子:

(defn integer-seq 
    [start] 
    (lazy-seq 
    (cons start (integer-seq (inc start))))) 
+0

那么*快*。谢谢! – 2010-11-23 10:02:21