my own interpose function as an exercise

╄→尐↘猪︶ㄣ 提交于 2019-12-23 20:25:39

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!