Wikiエンジンの開発

12.3 CGIの処理

loadContextの続き

まだまだ続きます、loadContext。
昨日は"dropComment"関数まで見ました。
今日は"parseLinePlain"関数です。
"parseLinePlain"関数の定義はこんな感じ。

    parseLinePlain line
        | isBlank line = []
        | otherwise    = let (k, ('=':v)) = break (== '=') . strip $ line
                         in [(strip k, strip v)]


引数"line"にはコメントを削除された(dropped)"./config"フイルの各行が入ってきます。
では中身を見ていきます。
二つの引数に関するガードで分岐されています。
一つ目が"line"に"isBlank"関数を適用してTrueを返すガード。
"isBlank"関数は以下の定義です。

  • TextUtil.hs
isBlank :: String -> Bool
isBlank = all isSpace


まぁ、おそらく指定された文字列がスペースで埋め尽くされてるかどうか判定しているのでしょう。
でもちょっと気になるので中身を見ていきます。
まず"all"って何?
これはPreludeモジュールで定義されています。

foldr            :: (a -> b -> b) -> b -> [a] -> b
foldr f z []     =  z
foldr f z (x:xs) =  f x (foldr f z xs)

and, or          :: [Bool] -> Bool
and              =  foldr (&&) True

all p            =  and . map p


う〜ん、深い!
引数のリストの全要素に対して、第一引数の関数を適用して
全ての結果がTrueの場合、Trueを返す…と思うのですが、
きちんと中を見ていきます。


これを馬鹿正直に展開(簡約?)してみると、

all isSpace
-- and . map isSpace
-- (foldr (&&) True) . map isSpace


ここまでは分かりました。
ここからがやっかいです。


関数合成の右辺は簡単です。
"isBlank"関数の第二引数のリストの全要素に対して"isSpace"関数を適用して、その結果をリストにします。
ちなみに"isSpace"関数はCharモジュールで定義されています。

isSpace c                =  c `elem` " \t\n\r\f\v\xA0"
        -- Only Latin-1 spaces recognized


スペース文字だけじゃなく、タブや改行もスペースとして扱ってるんですね。
ちなみに"elem"関数はPreludeモジュールで定義されています。

or               =  foldr (||) False

any, all         :: (a -> Bool) -> [a] -> Bool
any p            =  or . map p

elem, notElem    :: (Eq a) => a -> [a] -> Bool
elem x           =  any (== x)


あらら?また"foldr"関数が出てきた。
"isBlank"関数を読み解くには"foldr"関数の理解が必須なわけですね。


今日はここまで!