5
(defn square [x]
  (do
    (println (str "Processing: " x))
    (* x x)))

(println (map square '(1 2 3 4 5)))

出力はなぜ

(Processing: 1 
Processing: 2 
1 Processing: 3 
4 Processing: 4 
9 Processing: 5 
16 25)

いいえ

(Processing: 1
1 Processing: 2
4 Processing: 3 
9 Processing: 4 
16 Processing: 5 
25)

?

4

3 に答える 3

2

printlnは、その実装[[x & xs] xs]に分解形式を使用します。これは と同等であり、よりも遅延が少ないため、最初の項目を出力する前に 2 つの項目を認識します。[x (first xs), xs (next xs)]nextrest

例えば、

=> (defn fn1 [[x & xs]] nil)
#'user/fn1
=> (fn1 (map square '(1 2 3 4 5)))
Processing: 1
Processing: 2
nil
于 2012-11-20T03:45:59.163 に答える
2

map怠け者だから。の結果を事前にキャッシュするlazy-seqカバーの下で使用します。コードがシーケンスの最初の値を取得すると、2 つのステートメントが表示されます。restprintlnmap

このブログ記事も参照してください: Lazy Sequences

于 2012-11-19T14:45:30.817 に答える
1

コードスニペットで学ぶのは私のようですか? ここにあるいくつかの。

のドキュメントを見てみましょうmap

user=> (doc map)
-------------------------
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])
  Returns a lazy sequence consisting of the result of applying f to the
  set of first items of each coll, followed by applying f to the set
  of second items in each coll, until any one of the colls is
  exhausted.  Any remaining items in other colls are ignored. Function
  f should accept number-of-colls arguments.
nil

map遅延シーケンスを返します (@noahz によって提供された参照を既に読んでいる必要があります)。遅延シーケンスを完全に実現するには (遅延シーケンスは無限であり、終了しない可能性があるため、多くの場合、良い習慣ではありません)、dorunorを使用できますdoall

user=> (doc dorun)
-------------------------
clojure.core/dorun
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. dorun can
  be used to force any effects. Walks through the successive nexts of
  the seq, does not retain the head and returns nil.
nil
user=> (doc doall)
-------------------------
clojure.core/doall
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. doall can
  be used to force any effects. Walks through the successive nexts of
  the seq, retains the head and returns it, thus causing the entire
  seq to reside in memory at one time.
nil

それらは似ているように見えますが、そうではありません - 実現されたシーケンスの頭をどのように扱うかの違いに注意してください。

知識があれば、マップの遅延シーケンスが で動作する方法に影響を与えることができますdoall

user=> (defn square [x]
  #_=>   (println (str "Processing: " x))
  #_=>   (* x x))
#'user/square
user=> (doall (map square '(1 2 3 4 5)))
Processing: 1
Processing: 2
Processing: 3
Processing: 4
Processing: 5
(1 4 9 16 25)

お気づきかもしれませんが、関数内でsquare必要ないため、関数の定義も変更しました (マクロdoでは暗黙的です)。defn

Clojure Programming book には、次の場合に好きな文があります'(1 2 3 4 5)

「ほとんどの人は、メンバー式が常に評価されるような場合に単純にベクトル リテラルを使用します。」

この声明を裏付けるために関連するセクションをコピーする代わりに、時間とお金の価値があるので、この本をお勧めします.

于 2012-11-20T10:52:54.083 に答える