ドキュメンテーション文字列は、これらの機能が言う、のような、それ自体は配列ではありませんseqableコレクションに渡すときにseq
を自分で呼び出す必要はありませんアイデアを伝えるためにその引数にseq
を呼び出すことを言います、ベクトルまたはセット。 first
は、その引数にseq
を呼び出していませんでした場合たとえば、
(first [1 2 3])
;= 1
は動作しないでしょう。その代わりに、
(first (seq [1 2 3]))
と言う必要があります。これは不便です。
take
とdrop
も引数としてseq
を呼び出します。そうでない場合は、上で説明したようにベクターなどで呼び出すことができませんでした。実際、これはすべての標準的なseqコレクションに当てはまります。seq
を直接呼び出さないコレクションは、下位レベルのコンポーネントに基づいて構築されます。
これは、怠惰なseqの怠惰を損なうことはありません。 first
/rest
コールの結果として起こる強制/実現は、要求された結果を得るために可能な最小量である。 (それは引数のタイプに依存しますが、実際には怠惰でなければ、first
コールには余分な実現はなく、部分的に怠けている - チャンクされている - 余分なものがあります(最大32個の初期要素が一度に計算されます)、完全に怠けている場合は、最初の要素のみが計算されます。
明らかにfirst
を渡すと、最初の要素の実現が強制されます。それが全体のポイントです。 rest
は、実質的には、実際にはseqの「残りの部分」の実現を強制しないという点で、やや怠惰です(これは(seq (rest ...))
と基本的に同じであるnext
とは対照的です)。最初の要素を即座にスキップできるように、最初の要素を強制的に実行するという事実は、遅延seqオブジェクトの不必要なレイヤリングを回避し、元のseqの先頭を保持する意識的な設計選択です。遅いseqラッパーが実現するまで、xs
を保持するコストで、この初期実現を延期するために(lazy-seq (rest xs))
のようなものを言うことができます。
ありがとうございました。私は、チャンクされたものと完全に怠惰なものの違いは、私を捨てていたと思う。特にlazy-seqで最初に作業していたときに、私が作業していたものは、チャンクされたときに問題を引き起こしているはずだと思うので、それ以降はそれに固執しました。 – robertjlooby
はい、チャンク化すると予想外の結果につながる可能性があります。 'take 'は実装時に' first'と 'rest'の両方を使いますが、' drop'は 'rest'の上に構築されるので、助けにはなりません。unchunkingは可能ですが、チャンクされたseqの上に階層化された変換が一度に1つの要素だけ評価されるという意味でのみです。基礎となるチャンクされたseqは常にそのチャンクを完全に実現します。 (これを行う方法は、チャンクされたseqを元のseqをクロージャで 'reify clojure.lang.ISeq ... 'とした、unchunking seqでラップすることです) –
' take'/'drop'は実際に' seq'を呼び出しますか? replで試して 'class 'を'(range) '、'(take 1(range)) '、'(drop 1(range)) 'と呼ぶだけで' clojure.lang.LazySeq'となります。 '(rest(range))'、 '(seq(range)) 'を呼び出すと' clojure.lang.ChunkedCons'が返されます。 – robertjlooby