Haskellでgrep
30分プログラム、その386。Haskellでgrepを作ってみた。
最初、grep関数はこんな感じに書いてた。
grep r lines = let regex = mkRegex r in filter (containRegex regex) lines
で、いちど動いたあとに、どんどん引数を消していったら以下のようになった。
grep = filter . containRegex . mkRegex
こうやって引数をどんどん消していくのは、なかなかに楽しい。Perlの$_やコンテキストを使って、コードを短くしていくのと同質の快感を感じる。
これをさらに追求していくと、ゴルファーになれるんだろうな、たぶん。とりあえず、ボクはしばらくゴルファーにならなくてもいいや。
使い方
# grep $ ./grep Haskell diary.txt *amicable*[Haskell][30分プログラム]Problem21 -友愛数の和- *diag*[Haskell][30分プログラム]Problem28 *euler*[Haskell][30分プログラム]Problem32 ... # 正規表現も使える $ ./grep '\*{2} ' diary.txt ** 1 実数の絶対値 ** 2 立方根 ** 3 二分法 ** 6 状態不変表明 ...
ソースコード
import Text.Regex import System import System.IO -- cf. http://d.hatena.ne.jp/mzp/20080930/argf argf :: [String] -> (String -> IO ()) -> IO () argf args f = case args of [] -> getContents >>= f _ -> mapM readFile args >>= f . concat containRegex :: Regex -> String -> Bool containRegex regex str = matchRegex regex str /= Nothing grep :: String -> [String] -> [String] grep = filter . containRegex . mkRegex main = do (regex:args) <- getArgs argf args (putStrLn . unlines . grep regex . lines) return ()