銀天随筆集 このページをアンテナに追加 RSSフィード Twitter

2011-10-15 定理「野良メイド≒旦那様を見つけた野良メイド≠メイド」

otherwise パターン(?)

FizzBuzz とか FibBuzz で,

let n = case args of
          []        -> 30
          [x]       -> read x
          otherwise -> error "Invalid Program Option"

って何気なく書いてたけど,これ,よく考えるとおかしいです.


僕としては,ガードを使って

let x = case n of
          n | n < 0     = "negative"
            | otherwise = "not negative"

って書いてるつもりで otherwise を使ってたのですが,

最初のコードだと, otherwise はガードじゃなくてパターン部分に書かれてるよね.

otherwise パターンなんて物は存在しない筈なのに,なんでこれ,コンパイル通るんでしょうか?


結論をいってしまうと,これは単に, otherwise という変数に値を束縛しているだけです.

具体的に例を挙げて説明すると,

let n = case args of
          []        -> 30
          [x]       -> read x
          otherwise -> error $ show otherwise

上の case 式における show otherwiseotherwise は,

Prelude.otherwise ではなく args の中身が束縛される変数なので,

args として(例えば) ["1", "2"] を渡すと,

show otherwise"True" ではなく "[\"1\",\"2\"]" になります.


もちろん,本来なら,これは

let n = case args of
          []  -> 30
          [x] -> read x
          _   -> error "Invalid Program Option"

と書くべきです.

コンパイルエラーにならず,(結果的には)意図した通りの動作になるとはいえ,

パターンマッチ内のガードで Prelude.otherwise を使おうとした場合には,事故る可能性があるので.


後で書き直す.

nobsunnobsun 2011/10/16 17:43 パターン内の変数は局所変数なのでエラーにはなりませんが、-Wallなどを指定しておけば「既存の束縛を隠してしまうよ」という警告は出るとおもいますよ。

gintenlabogintenlabo 2011/10/16 18:29 警告が出るとしたら,むしろ未使用変数な気がします.
こういう小さなプログラムは GHCi で実行するのが常なので,試してないですが.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/gintenlabo/20111015/1318689620