2006-07-28
■[Haskell] 逆ポーランド電卓をつくってみました

ふつけるを7章くらいまで読み終えたので、この辺で一旦本から離れて自分でプログラムを書いてみました。僕は「新しい言語を覚えるときには逆ポーランド電卓から」と決めているので、今回も逆ポーランド電卓を作ってみました。うーむ、op_*関数のあたりとエラー処理がいまひとつおさまりが悪いです。
import System
main :: IO ()
main = do args <- getArgs
print $ rpcalc [] $ concatMap words args
rpcalc :: [Integer] -> [String] -> Integer
rpcalc (x:[]) [] = x
rpcalc _ [] = error "illegal expression."
rpcalc stack (x:xs)
| x == "+" = rpcalc (op_plus stack) xs
| x == "-" = rpcalc (op_minus stack) xs
| x == "*" = rpcalc (op_mult stack) xs
| x == "/" = rpcalc (op_div stack) xs
| otherwise = rpcalc ((strToInteger x) : stack) xs
where
op_plus :: [Integer] -> [Integer]
op_plus (x1:x2:xs) = (x2 + x1) : xs
op_plus _ = error "illegal expression(+)."
op_minus :: [Integer] -> [Integer]
op_minus (x1:x2:xs) = (x2 - x1) : xs
op_minus _ = error "illegal expression(-)."
op_mult :: [Integer] -> [Integer]
op_mult (x1:x2:xs) = (x2 * x1) : xs
op_mult _ = error "illegal expression(*)."
op_div :: [Integer] -> [Integer]
op_div (0:_:_) = error "can't divid by 0."
op_div (x1:x2:xs) = (x2 `div` x1) : xs
op_div _ = error "illegal expression(/)."
strToInteger :: String -> Integer
strToInteger s = (read :: String -> Integer) s
以下、実行例です。
$ ./rpcalc.exe "1 2 + 4 * 2 /" 6
そうそう今さらながら気が付いたのですが、逆ポーランド記法って日本語と相性がよいですね。例えば、上の実行例の式は、「1と2を足して(+)、それに4を掛けて(*)、その結果を2で割る(/)」と読めます。日本語の語順です。
コメントを書く
トラックバック - http://d.hatena.ne.jp/ha-tan/20060728/1154060849
リンク元
- 5 http://d.hatena.ne.jp/keyworddiary/堂本剛?date=20060726
- 4 http://d.hatena.ne.jp/keyworddiary/Haskell
- 4 http://m.ld.tv/extlink/?.next=http://d.hatena.ne.jp/ha-tan/20060726/1154062171
- 4 http://www.google.co.jp/search?hl=ja&q=rfc4180&lr=
- 3 http://blog.goo.ne.jp/search/search.php?status=select&tg=all&st=time&dc=10&dp=all&da=all&ts=&MT=時をかける&st=time
- 3 http://d.hatena.ne.jp/keyworddiary/堂本剛
- 2 http://blog-search.yahoo.co.jp/search?p=時をかける少女&n=10&so=&b=2
- 2 http://blog-search.yahoo.co.jp/search?p=良元優作&n=10&so=&b=4
- 2 http://d.hatena.ne.jp/keyword/食わず嫌い王決定戦?kid=33003
- 2 http://d.hatena.ne.jp/keyworddiary/時をかける少女?date=20060724


