[過去ログ] 関数型プログラミング言語Haskell Part7 (1001レス)
上下前次1-新
抽出解除 レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
897(1): 2007/09/21(金)21:07 AAS
>>895
それで合ってる。seqを中置で使うのは良く見かける気がする。
seqを使っているのは再帰に入る前にelts_lt_xとelts_greq_xを完全に評価するため。
未評価のelts_greq_xのサンクはxsを参照しているけど、
完全に評価してしまえばただのリストなので、xsへの参照がなくなって、
GCがxsを回収できるようになる。
seq A Bの値はBと同じだけど、この式を評価する時はまずAを評価して、
その結果を捨て、改めてBを評価する。
length elts_lt_x `seq` 本体
を評価するときは、まずelts_lt_xの長さを求めることになるが、
リストの長さを求めるにはリスト全体を評価する必要がある。
結局、本体が評価される前にelts_lt_xが完全に評価される。
lengthが必要な理由には、seqの仕様が関わってくる。
seq A Bが評価されるとき、Aは弱冠頭正規形(weak head normal form, WHNF)まで簡約される。
WHNFというのは、最も外側のデータ構築子が確定した形。
例えば1+2や[1,2]++[3,4]はWHNFじゃないけど、3や1:([2]++[3,4])はWHNF。
だから、lengthを使わずに
elts_lt_x `seq` 本体
のように定義すると、例えば
elts_lt_x = [y | y <- [1, 2, 3, 4], y < 5]
のとき、これを
elts_lt_x = 1 : [y | y <- [2, 3, 4], y < 5]
と簡約したら、この段階でWHNFに達したことになり、評価が終わってしまう。
これだと、xs(ここでは[2, 3, 4])への参照が残っていて、GCがxsを回収できない。
901: 2007/09/21(金)22:02 AAS
>>897
力作ありがとうございます。
seqは完全に遅延評価を回避できるわけではないんですね。なんというか、オブジェクト指向言語でよく出てくるshallow copyとdeep copyの違いみたいな感じでしょうか(つまりseqはshallow copyに似ている)。
しかし完全に評価するためにlengthを使うのって、bad know howですよね。
このためにlengthを使うのは、lengthの本来の用途ではないのだから、完全に評価するための専用の関数が標準で用意されるべきたと思いました。たとえその実体がlengthであったとしても。
上下前次1-新書関写板覧索設栞歴
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 0.179s*