2013-10-01 3 views
0

На http://clojure.org/lazy, filter определяется следующим образом:Реализация отложенного фильтра в Clojure

(defn filter 
    "Returns a lazy sequence of the items in coll for which 
    (pred item) returns true. pred must be free of side-effects." 
    [pred coll] 
    (let [step (fn [p c] 
       (when-let [s (seq c)] 
        (if (p (first s)) 
        (cons (first s) (filter p (rest s))) 
        (recur p (rest s)))))] 
    (lazy-seq (step pred coll)))) 

Важно, что рекурсивный вызовом является filter, не step? Если да, то почему?

ответ

1

Это с остальной частью кода, как указано здесь, потому что это filter, который делает обертку в lazy-seq. Если бы step называл себя, он бы делал всю фильтрацию сразу, а не лениво.

(Обновлено). Если lazy-seq был добавлен в step «s тела, step мог бы назвать себя и по-прежнему быть ленивым. Это может быть достигнуто, по крайней мере в этих двух направлениях:

  1. путем обертывания всего тела в lazy-seq и замена как рекурсивный вызов filter и recur с вызовами step; NB. в этом случае необходимо будет назвать функцию step (либо путем замены let на letfn с соответствующим изменением синтаксиса, либо путем добавления имени в форму fn: (fn step ...)); тогда lazy-seq обертывание внешнего вызова на step было бы ненужным; также, на данный момент вы можете просто не иметь внутренней вспомогательной функции (просто используйте этот подход в filter);

  2. , оставляя lazy-seq в filter на месте и оберточной рекурсивный вызов в step (который теперь будет самые step) в lazy-seqrecur формы остается неизменной).

Обратите внимание, что clojure.core/filter имеет другую реализацию, с раздельной обработкой логики фрагментированной последовательности и никаких внутренних вспомогательными функций. В не-chunked случае он работает как версия step, описанная в 1. выше.

+0

Но если я обернуваю все тело 'lazy-seq', то' recur' не будет находиться в хвостовой позиции – tempestadept

+0

@tempestadept. Право, вам придется заменить его на другой рекурсивный вызов. ('clojure.core/filter' эффективно работает так, как в случае с неядерным.) Я отредактировал ответ, чтобы принять это во внимание. –

Смежные вопросы