簡易cat (2)
ファイル内容を表示するだけでは寂しいので、コマンドラインに オプションを追加してみる。ややこしいのは大変なので、先頭に 行番号を表示する -n モドキだけ。
-n オプションがある場合は各行の表示をする時に番号を付加する。 行番号はいわゆる「無限リスト」を各行とzipで組にしてみた。
Cat4.hs
-- -- Cat4 -- module Main ( main ) where import System.Environment main :: IO () main = do xs <- getArgs putFiles $ checkArgs xs checkArgs :: [String] -> (Bool, [String]) checkArgs [] = (False, []) checkArgs (x:xs) | x == "-n" = (True, xs) | otherwise = (False, (x:xs)) putFiles :: (Bool, [String]) -> IO () putFiles (_, []) = putStr "" putFiles (b, (x:xs)) = do cs <- readFile x putStr (decorate b cs) putFiles (b, xs) decorate :: Bool -> String -> String decorate False cs = cs decorate True cs = unlines $ map tr (zip [1..] $ lines cs) tr :: (Int, String) -> String tr (n, l) = (show n) ++ "\t" ++ l
単に最初の引数が"-n"かどうかをチェックしているだけなのに 結構邪魔くさいことになっている。 doブロック内でできることできないことについて、下記ではまった。
putFiles (b, (x:xs)) = do cs <- readFile x putStr (decorate b cs)
putStrのところ、今回は短いのでいいが、一旦変数にバインドしようとして 単に代入文を書いたらコンパイルエラーになった。
cs' = decorate b cs
putStr cs'
しょうがないのでputStr一行にまとめてしまったが、あとで試したらletを 使えば大丈夫そう。
let cs' = decorate b cs putStr cs'
一方で where句ではエラーになった。csがスコープにないと怒られたので where句の中に"cs <- readFile x"を書いてもエラーになってしまう。
putStr cs' where cs' = decorate b cs
letとwhereの違いを確認しておこう。
次回は使えそうなプログラムを作ってみる。