Concurrent Clean : 正格性解析
http://d.hatena.ne.jp/tanakh/archive?word=wcを見ながら、Cleanでどういうチューニングがありえるかを考えていた。
文字の読み込みをバッファリングしてみようかと思って、
::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)
というコードを書いてみたのだが・・・
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)
やってみると、"Heap Full"とか言われる。なんじゃそりゃ?
で、どこで文句をいわれるのかと、abortを挿入してみた。
::BufferedFile = Buffered !.File !.{#Char} !Int !Int buffering f = Buffered f "" 0 0 bfreadc :: !*BufferedFile -> (!Bool, !Char, !*BufferedFile) bfreadc (Buffered f cs i j) | j > 10000000 = abort ("read " +++ toString (j*100)) # j = j+1 # (len, cs) = usize cs | i < len # (c, cs) = cs![i] = (True, c, Buffered f cs (i+1) j) # (cs, f) = freads f 100 # (len, cs) = usize cs | 0 == len = (False, '\0', Buffered f cs 0 j) # (c, cs) = cs![0] = (True, c, Buffered f cs 1 j)
そうしたら、エラーなく終了するようになった。
なぜ?