逆ポーランド電卓をつくってみました
ふつけるを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で割る(/)」と読めます。日本語の語順です。
参照: id:ha-tan:20050914:1126649914