lazy-sequence with recursion: переполнение стека в некоторых случаях с repl - PullRequest
0 голосов
/ 11 сентября 2018

Я играю с clojure, точнее с ленью.Я попробовал этот кусок кода:

(defn even-numbers
  ([] (even-numbers 0))
  ([n] (cons n (lazy-seq (even-numbers (+ n 2))))))
(take 1 (even-numbers 0))

Это довольно идиоматично, я не думаю, что с этим что-то не так.

Проблема в том, что я использую cider в emacs.Если я сначала оцениваю defn, а потом оцениваю вызов функции, я получаю переполнение стека.Оценка всего буфера в порядке.

Я подозреваю, что виноват режим просветления, так как я не получаю переполнение, когда отключаю его.Я просто хочу понять, что здесь происходит.

[РЕДАКТИРОВАТЬ] Я совершенно уверен, что проблема связана с режимом просветления сидра.отключая его, я никогда не получаю переполнение стека.

Чтобы немного углубиться в это, учитывая слегка измененный отрывок:

(ns clojure-noob.bizarerrie)

(defn even-numbers
  ([] (even-numbers 0))
  ([n] (do (println (even-numbers (+ n 2)))
           (cons n (lazy-seq (even-numbers (+ n 2)))))))
(take 1 (even-numbers 0))

, который также дает переполнение стека в каждом случае.Так как в режиме просветления попытайтесь разрешить выражение для вывода во время выполнения на лету;Интуитивно я бы сказал, что он пытается напечатать форму (even-numbers (+ n 2)) (например, только что добавленную печать), что вызывает переполнение стека.

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

у вас есть cons и lazy-seq, переключенные в ленивом определении последовательности:

Вот оно с cons внутри lazy-seq

user> (defn even-numbers [n]
        (do
          (lazy-seq (cons (do
                            (printf "creating value %s for lazy sequence" n)
                            n)
                          (even-numbers (+ n 2))))))
#'user/even-numbers

И снова с cons вне lazy-seq, который создает почти ленивую последовательность

user> (defn even-numbers-not-really-lazy [n]
        (do
          (cons (do
                  (printf "creating value %s for lazy sequence" n)
                  n)
                (lazy-seq (even-numbers (+ n 2))))))

Правильная ленивая последовательность не должна работать при ее создании , давайте проверим оба из них:

#'user/even-numbers-not-really-lazy
user> (def lazy-even-numbers
        (even-numbers 0))
#'user/lazy-even-numbers

Да, это выглядит хорошо, теперь с минусами снаружи:

user> (def not-lazy-even-numbers
        (even-numbers-not-really-lazy 0))
creating value 0 for lazy sequence
#'user/not-lazy-even-numbers

хммм, похоже, что мы проделали некоторую работу, когда создавали ячейку "против".

0 голосов
/ 11 сентября 2018

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

(take 10 (even-numbers 0)) ; if you want to realize first 10 values
...