6

の各要素を処理するとき、seq通常はfirstrestを使用します。ただし、これらは、引数lazy-seqを呼び出すことによって a の「怠惰」を失わせます。seq私の解決策は、s を操作するときに(first (take 1 coll))and(drop 1 coll)を代わりに使用することでした。それで問題ないlazy-seqと思いますが、最初の要素drop 1を呼び出して取得する必要は特にありませんfirsttake

これを行うためのより慣用的な方法はありますか?

4

1 に答える 1

10

firstおよびsayのドキュメント文字列はrest、これらの関数が引数を呼び出すことで、ベクトルやセットなど、それ自体が seq ではない seqable コレクションを渡すときに自分自身seqを呼び出す必要がないという考えを伝えます。seq例えば、

(first [1 2 3])
;= 1

引数をfirst呼び出さないと機能しません。seqあなたは言わなければならないでしょう

(first (seq [1 2 3]))

代わりに、これは不便です。

両方ともtake引数をdrop呼び出しseqます。そうしないと、上記で説明したように、ベクトルなどでそれらを呼び出すことができません。実際、これはすべての標準的な seq コレクションに当てはまります。直接呼び出さないものは、呼び出すseq下位レベルのコンポーネントに基づいて構築されています。

これにより、レイジー seq の遅延性が損なわれることはありません。first/呼び出しの結果として発生する強制 / 実現restは、要求された結果を得るために可能な最小量です。(それがどの程度かは、引数の型によって異なります。実際に遅延していないfirst場合、呼び出しに追加の実現は含まれません。部分的に遅延している場合、つまりチャンクされている場合は、追加の実現が行われます。 (最大 32 の初期要素が一度に計算されます); 完全に遅延している場合、最初の要素のみが計算されます。)

明らかfirstに、lazy seq が渡された場合、その最初の要素の実現を強制する必要があります。これが要点です。restは、実際には seq の「残りの」部分の実現を実際に強制しないという点で、やや怠惰です (nextこれは、基本的に と同等である とは対照的です(seq (rest ...)))。すぐにスキップできるように最初の要素を強制的に実現するという事実は、遅延 seq オブジェクトの不必要なレイヤー化と元の seq のヘッドの保持を回避する意識的な設計上の選択です。レイジー seq ラッパーが実現さ(lazy-seq (rest xs))れるまで保持することを犠牲にして、この最初の実現でさえ延期するようなことを言うことができます。xs

于 2013-08-06T02:49:44.877 に答える