Concurrent Clean : 文字列のバッファリング (2)
[id:lethevert:20060215:p2]の続き。
正格性に関する注釈を細かく入れることで、Heap Fullエラーを起こさないようになりました。
Start world #(console,world) = stdio world #(nl,nw,nc) = wc (buffering console) = toString nl +++ " " +++ toString nw +++ " " +++ toString nc wc f = inner f 0 0 0 True where inner f nl nw nc prev #(b,c,f) = bfreadc f # nprev = isSpace c # nnl = nl + if (c=='\n') 1 0 # nnw = nw + if (prev&¬ nprev) 1 0 # nnc = nc + 1 | b = inner f nnl nnw nnc nprev | otherwise = (nl,nw,nc) ::*BufferedFile = Buffered !*File !*{#Char} !Int buffering f = Buffered f "" 0 bfreadc :: !*BufferedFile -> (!Bool, !Char, !*BufferedFile) bfreadc (Buffered f cs i) #! (len, cs) = \!! $ usize cs | i < len #! (c, cs) = \!! $ cs![i] = (True, c, Buffered f cs (i+1)) #! (cs, f) = \!! $ freads f 100 #! (len, cs) = \!! $ usize cs | 0 == len = (False, '\0', Buffered f cs 0) #! (c, cs) = \!! $ cs![0] = (True, c, Buffered f cs 1)
パフォーマンスはあまり変わらないような気がしますが・・・
一意な文字列を使っていますが、次のように一意でないものにすると、回避できませんでした。
::*BufferedFile = Buffered !*File !{#Char} !Int buffering f = Buffered f "" 0 bfreadc :: !*BufferedFile -> (!Bool, !Char, !*BufferedFile) bfreadc (Buffered f cs i) | i < size cs #! c = cs.[i] #! i = i+1 = (True, c, Buffered f cs i) #! (cs, f) = \!! $ freads f 100 | 0 == size cs = (False, '\0', Buffered f cs 0) #! c = cs.[0] = (True, c, Buffered f cs 1)
共有があるせいで、メモリの解放が上手いかないのかな?