问题
I'm resolving a 4Clojure exercise, this exercise asks you to build your own interpose function. My answer follows:
(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))))))
I'm doing these exercises to learn the language as I read a Clojure book. I will like to know the opinion about my code of people with an experience in the language. Could I avoid the reverse call? Are there any conventions I'm breaking hardly with this kind of code?
回答1:
What you have is a good proper starting point :). Excellent work.
Starting with what you have you may want to:
Replace your recursive call with a call to
recur
because as written it will hit a stack overflow(defn foo [stuff] (dostuff ... ) (foo (rest stuff)))
becomes:
(defn foo [stuff] (dostuff ...) (recur (rest stuff)))
to avoid blowing the stack. this then often becomes:
(map dostuff stuff)
Replace the recustion entirely with the
for
function(for [a one-list b another-list] (dont-give-away-the-answer))
回答2:
Yes you can avoid the reverse call,
(defn my-interpose [sep coll]
(when (seq coll)
(lazy-cat [(first coll) sep]
(my-interpose sep (rest coll)))))
as arthur suggest you can use recur in order to not to blow the stack but 99% of the time you don't need it.
EDIT:
This is a bit cleaner,
(defn my-interpose [sep coll]
(if-let [[first & rest] coll]
(lazy-cat [first sep] (my-interpose sep rest))))
回答3:
Got to various answers using mapcat and for but in the end I found this:
#(rest (interleave (repeat %1) %2))
Where the first argument is the separator and the second is the collection. Just posting this answer for pure curiosity of other Clojure noobs like me.
回答4:
Here is my solution, trying to rely on lower-level lisp or scheme-like functions.
(defn my-interpose[sep coll]
(letfn [(f [c]
(when-not (empty? c)
(cons sep (cons (first c)
(f (next c))))))]
(next (f coll))))
回答5:
You may want to use map
(defn my-interpose [sep coll]
(rest (apply concat (map #(vector sep %) coll))))
or a directly a reduce and compute the answer as you go
(defn my-interpose [sep coll]
(rest (reduce #(conj %1 sep %2) [] coll)))
The idea behind this is to compute a sequence like (sep x0 sep x1 sep x2 ... sep xn)
and then skip the first element to get (x0 sep x1 sep x2 ... xn)
.
来源:https://stackoverflow.com/questions/7574416/my-own-interpose-function-as-an-exercise