0

「反復は無限の遅延シーケンスを提供します」

 (= (range 20) (take 20 (iterate inc 0)))

私の質問は、なぜ 1 ではなく 0 から始まるのですか? ここで怠惰を理解する方法は?

4

2 に答える 2

3

デフォルトでは 0 から開始するため、公案では反復を 0 から開始するよう求めておりrange、見栄えの良いステートメントになっています。プログラミングでは、1 ではなく 0 からカウントを開始するのが一般的で便利です。

(= (range 1 21) (take 20 (iterate inc 1)))

これが iterate の定義方法です

user=> (source iterate)
(defn iterate
  "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
  {:added "1.0"
   :static true}
  [f x] (cons x (lazy-seq (iterate f (f x)))))

というわけで、(iterate inc 0)まずはこんな感じ

(cons 0, (lazy-seq (iterate inc (inc 0))))

ここで、位置 1 (つまり、0 から数えてから 2 番目の位置) にある特別な lazy-seq 要素が最初にアクセスされると、事実上、その展開によって置き換えられます。

 -- (iterate inc (inc 0)) 
 -> (iterate inc 1) 
 -> (cons 1, (lazy-seq (iterate inc (inc 1))))

したがって、シーケンスは次のようになります

-- (cons 0, (lazy-seq (iterate inc (inc 0))))
-> (cons 0, (cons 1 (lazy-seq (iterate inc (inc 1)))))

2 番目の位置にある特別な lazy-seq 要素が最初にアクセスされると、実際には展開によって置き換えられます。

 -- (iterate inc (inc 1)) 
 -> (iterate inc 2) 
 -> (cons 2, (lazy-seq (iterate inc (inc 2))))

したがって、シーケンスは次のようになります

 -- (cons 0, (cons 1 (lazy-seq (iterate inc (inc 1)))))
 -> (cons 0, (cons 1, (cons 2, (lazy-seq (iterate inc (inc 2))))))

注意が必要な結果もありますが、通常、新しいユーザーとして心配する必要はありません

  • ボディ内の副作用はアクセスされるまで実行されず、一度だけ実行されます
  • with-完全に実現されていない遅延シーケンスを返す可能性があるため、ブロック内で返すなど、動的スコープへの依存に注意してください。
  • たとえば、長い/無限の遅延シーケンスへの参照を保持し(def numbers (iterate inc 0))、それらの束を実現すると、それらはメモリに残ります。これが問題になる場合は、「頭を抱える」ことは避けてください。
于 2014-02-14T05:01:16.613 に答える
2

clojure.core/iterateは 2 つの引数を取ります:

  1. fnをシーケンスの最後の要素に適用します。適用すると、シーケンス内の次の要素が生成されます

  2. シーケンスの初期値

(iterate inc 0)0シーケンスの最初の要素として持っています。

(take 1 (iterate inc 0)) ;; (0)
于 2014-02-14T03:06:13.867 に答える