我自己的插入功能作为练习

时间:2011-09-27 19:07:37

标签: clojure

我正在解决一个4Clojure练习,这个练习要求你建立自己的插播功能。我的答案如下:

(fn my-interpose 
  ([separator input] (my-interpose separator input nil))
  ([separator input result] 
    (if 
      (empty? input) 
      (reverse (rest result))
      (my-interpose separator (rest input) (cons separator (cons (first input) result))))))

我正在做这些练习,以便在阅读Clojure书时学习语言。我想知道有关我的语言经验的人的代码的意见。我可以避免反向通话吗?是否有任何约定我几乎没有破坏这种代码?

6 个答案:

答案 0 :(得分:5)

你所拥有的是一个很好的起点:)。出色的工作。

从您拥有的内容开始,您可能希望:

  • 通过调用recur来替换您的递归调用,因为写入会导致堆栈溢出

    (defn foo [stuff]
      (dostuff ... )
      (foo (rest stuff)))
    

    变为:

    (defn foo [stuff]
      (dostuff ...)
      (recur (rest stuff)))
    

    避免吹栈。然后经常变成:

    (map dostuff stuff)

  • 完全用for函数

    替换recustion
    (for [a one-list b another-list]
      (dont-give-away-the-answer))
    

答案 1 :(得分:3)

是的,你可以避免反向通话,

(defn my-interpose [sep coll]
  (when (seq coll)
    (lazy-cat [(first coll) sep]
              (my-interpose sep (rest coll)))))

因为亚瑟建议你可以使用复发以便不用吹掉堆叠,但99%的时间你不需要它。

编辑:

这有点清洁,

(defn my-interpose [sep coll]
  (if-let [[first & rest] coll]
    (lazy-cat [first sep] (my-interpose sep rest))))

答案 2 :(得分:2)

使用mapcat得到了各种答案,但最后我发现了这个:

#(rest (interleave (repeat %1) %2))

第一个参数是分隔符,第二个参数是集合。只是发布这个答案,以满足像我这样的其他Clojure新手的纯粹好奇心。

答案 3 :(得分:1)

这是我的解决方案,试图依赖较低级别的lisp或类似方案的函数。

(defn my-interpose[sep coll]                                                                                                                                                                                                                
  (letfn [(f [c]                                                                                                                                                                                                                            
            (when-not (empty? c)                                                                                                                                                                                                            
              (cons sep (cons (first c)                                                                                                                                                                                                     
                              (f (next c))))))]                                                                                                                                                                                             
    (next (f coll))))

答案 4 :(得分:1)

您可能想要使用地图

(defn my-interpose [sep coll]
  (rest (apply concat (map #(vector sep %) coll))))

或直接 reduce 并随时计算答案

(defn my-interpose [sep coll]
  (rest (reduce #(conj %1 sep %2) [] coll)))

这背后的想法是计算像(sep x0 sep x1 sep x2 ... sep xn)这样的序列,然后跳过第一个元素来获得(x0 sep x1 sep x2 ... xn)

答案 5 :(得分:0)

仅使用reduce and conj:

(defn my-interpose [sep a-seq]
  (if (empty? a-seq)
    a-seq
    (reduce (fn [e1 e2] (if (empty? e1)
                          (conj e1 e2)
                          (conj e1 sep e2))) [] a-seq)))