Clojureでレイジーシーケンスを非レイジーに変換する方法


95

非遅延シーケンスのクラスが返されることを期待して、Clojureで次のことを試しました。

(.getClass (doall (take 3 (repeatedly rand))))

ただし、これはまだを返しますclojure.lang.LazySeq。私の推測では、doallシーケンス全体が評価されますが、メモ化には引き続き役立つため、元のシーケンスが返されます。

では、遅延シーケンスから非遅延シーケンスを作成する慣用的な方法は何ですか?


戻り値の実際の型についてなぜ心配しているのか誰も尋ねなかったのには驚きです。doall
tar

ベクトルに変換できます:(vec (take 3 (repeatedly rand)))
Kris

回答:


161

doallは、あなたが必要とすることすべてです。seqhasタイプLazySeqがあるからといって、保留中の評価があるという意味ではありません。Lazy seqは結果をキャッシュするため、すべてを強制するためにLazyをseq1回歩くだけで(そうするようにdoall)、Lazyをレンダリングします。コレクション全体の評価を強制seqしませ


2
これを承認済みの回答に変更しました。関連するメモとして、LazySeqが以前に評価されているかどうかをどのように判断できますか?
Tim Clemons、

10
私はあなたが電話するだけだと思いますrealized?
12

1
おそらくrealize一致する操作があるはずrealized?です。
Reut Sharabani、2017

これはすべてとてもいいです。しかし、のような一部の関数contains?は、怠惰なシーケンスを実現したかどうかを気にしないので、これは質問どおりに特定の質問に答えますが、質問のタイトルには答えません。
matanster

75

これはある程度分類法の問題です。レイジーシーケンスは、リスト、ベクトル、またはマップと同様に、1種類のシーケンスにすぎません。したがって、答えはもちろん「取得したい非レイジーシーケンスのタイプによって異なり
ます。以下から選択してください。

  • ex-lazy(完全に評価された)lazy sequence (doall ... )
  • 順次アクセスのリスト (apply list (my-lazy-seq)) OR (into () ...)
  • 後でランダムアクセスするためのベクトル (vec (my-lazy-seq))
  • 特別な目的がある場合は、マップまたはセット。

ほとんどのスイートは、どのタイプのシーケンスでも必要に応じて持つことができます。


これが最良の答えです。
フェリペ14

4
受け入れられた答えは技術的に正しいですが、この答えは私にとって最も役に立ちました。ベクトルに関数をマップし、結果をファイルに吐き出そうとしていましたが、doallを呼び出した後でも、ファイルにはシーケンスの内容ではなく「clojure.lang.LazySeq@address」が含まれていました。返された値マップでvecを呼び出すと、ファイルに吐き出すために必要なものが得られました。
ジェシーロザリア2015年

1
@JesseRosalia SO全体で唯一のリッチヒッキーの応答が技術的に正しかったことを知っておくのは良いことです。;-)
Phil Cooper、

(vec (my-lazy-seq))次のような状況ではそれほど良くありません: (vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]からcheshireレイジー(json/parse-string)
シーケンス

上記の緩和策は、eager(json/parse-string-strict)
codeasoneを

22

この裕福な男は彼の陰謀を知っているようで、絶対に正しいです。
しかし、あなたの例を使用したこのコードスニペットは、この質問を補足するのに役立つと思います。

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

確かには変わっていませんが、実現


2
ただし、シーケンス全体を強制的realized?に戻す必要がないことに注意してくださいtrue。例えば(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
アレックス・コベントリー

22
この金持ちの男:D
ハハ

10
@nimrod :)駄洒落は、しかし、「彼のclojure」にあることを意味していました。
Peter

10
知らない人のために、「金持ち」はClojureを発明しました。
erturne 2014年

1
@AlexCoventryあなたの例が返す[true true]

7

再帰的でないことについて、このブログ投稿を偶然見つけましたdoall。そのため、投稿の最初のコメントがうまく機能していることがわかりました。以下に沿ったもの:

(use 'closure.walk)
(postwalk identity nested-lazy-thing)

mapエラー状態を強制するために、いくつかの入れ子になったアプリケーションの評価を強制したい単体テストで、これが便利であることがわかりました。


5
(.getClass (into '() (take 3 (repeatedly rand))))

3
これはひどい考えです。入力シーケンスを逆にします。
アマロイ2011

3
もちろん、この場合、入力を反転しても違いはありません。これは、それらが3つの乱数であるためです。...:-)
mikera
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.