Я сам выполняю функцию дубля - PullRequest
0 голосов
/ 29 декабря 2018

Я пытаюсь сделать функцию take самостоятельно, но, похоже, это вызывает переполнение стека, есть идеи, что может быть причиной этого?

(defn my-take-plus [n Lst LstAcc count]
  (let [LstVec (into [] Lst)]
    (cond (= count n) LstAcc
    :else 
      (do
         (conj LstAcc (first LstVec))
         (inc count)
         (my-take-plus n (apply list(rest LstVec)) LstAcc count)
      )
   )
 )
)


(defn my-take [n Lst]
  (my-take-plus n Lst [] 0)
)

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Кроме того, есть еще один «clojurish» способ сделать это:

(defn my-take [n data]
  (when (and (pos? n) (seq data))
    (lazy-seq
     (cons (first data)
           (my-take (dec n) (rest data))))))

этот ленивый, а также предотвращает переполнение стека. Более того, насколько я помню, clojure.core/takeреализован аналогичным образом

0 голосов
/ 29 декабря 2018

Я бы рассмотрел использование стратегии loop/recur, чтобы Clojure выполнял оптимизацию хвостовых вызовов (TCO) для предотвращения переполнения стека.

(defn take' [n coll]
      (loop [n    n
             acc  []
             coll coll]
        (cond
          (empty? coll) acc
          ((comp not pos?) n) acc
          :else (recur (dec n) (conj acc (first coll)) (rest coll)))))

В вашем примере я бы рассмотрел использование if так как у вас были только условные ветки.cond обычно используется больше как выражение case.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...