我正在解决一个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书时学习语言。我想知道有关我的语言经验的人的代码的意见。我可以避免反向通话吗?是否有任何约定我几乎没有破坏这种代码?
答案 0 :(得分:5)
你所拥有的是一个很好的起点:)。出色的工作。
从您拥有的内容开始,您可能希望:
通过调用recur
来替换您的递归调用,因为写入会导致堆栈溢出
(defn foo [stuff]
(dostuff ... )
(foo (rest stuff)))
变为:
(defn foo [stuff]
(dostuff ...)
(recur (rest stuff)))
避免吹栈。然后经常变成:
(map dostuff stuff)
完全用for
函数
(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)))