save and load 完成
昨日コンパイルエラーに悩まされて中断して寝てしまったLoad関数のパーサ。
今再挑戦したらすぐにできました。
よかったよかった。
というわけで。
今朝書いた、parseRun及びparseListと、その他。
最後のreturn関数部分をどう書いたらいいか悩んでいたんですが、数式のパーサと同様にしたらできました。
module LoadParse where import Text.Parsec import Text.Parsec.String import Types --for example,[(0,"123.jpg"),(2,"r.png"),(21,"l.png")] parseRun :: Parser ScreenState -> String -> IO ScreenState parseRun p str = case (parse p "" str) of Left _ -> return [] Right x -> return x parseList :: Parser ScreenState parseList = do char '[' l <- factor rs <- many (do char ',' x <- factor return $ (++) [x] ) char ']' return $ foldr ($) [l] rs factor :: Parser Image factor = do char '(' layer <- layerTerm char ',' fname <- fileTerm char ')' return (layer,fname) fileTerm :: Parser ImageFile fileTerm = do char '\"' k <- many( letter <|> digit <|> (char '.' >> return '.')) char '\"' return k layerTerm :: Parser Int layerTerm = read<$>many1 digit
saveデータがない場合も正常に機能して、空リストを返します。
load部は、以下のように書きなおすだけです
(実際にはextract関数だけに変更)
datanum :: Int datanum = 3 load :: Int -> IO (Date,FLine,ScreenState,Music) load k = do h <- openFile datafile ReadMode fs <- hGetContents h result <- extract.pickedData $ fs return result where pickedData = take datanum.drop (k*datanum).lines extract :: [String] -> IO (Date,FLine,ScreenState,Music) extract [l1,l2,l3] = parseRun parseList l2 >>= \scr -> return (date,read n,scr,mg) where (date:n:_) = words $ l1 mg :: Music mg = case l3 of "Silence" -> Silence otherwise -> PlayOn $ last.words $ l3
loadするセーブデータを始まりを
0番目とするか1番目するかによって、load関数内のkを、kとして扱うか、k-1として扱うかが変わりますが、変更するとしてもその個所だけなのでデバッグは容易ですね。
Haskellやり始めてから、
関数を細かく分けて作業することがどれだけ楽か実感します。
CやC++しか知らなかった時には、一つの関数に機能詰め込み過ぎて、今はとてもじゃないけど読む気力ない....