アヤチノオト

覚書のこと

すごいE本読んでる記録

すごいE本ことすごいErlangゆかいに学ぼう!を読んでいます。
タイトルからわかるとおり、すごいHaskellたのしく学ぼう!の読みやすく、それでいて深い内容のスタイルを真似て書かれています。
すごいH本とおなじ問題がすごいE本にも出ていて、その中の逆ポーランド記法電卓をやってみました。

逆ポーランド記法とは

まずポーランド記法が何かというと。Lispの括弧を取ったようなやつです。

// 普通の式
(1 + 2) * 3
// ポーランド記法
* 3 + 1 2

逆ポーランド記法はこれをひっくり返したものです。

// 逆ポーランド記法
1 2 + 3 *

演算子が必ず先に来るので評価がシンプルに出来ます。

書いてみた

本の中のコードでは演算子が"+"みたいに文字列だったんですがこれをaddみたいにatomを使ってみた。

%% rpn("1 2 add 3 mul") = 9
rpn(L) when is_list(L) ->
    % 文字列を空白で区切って,integerかfloatかatomのリストにする
    Values = lists:map(fun read/1, string:tokens(L, " ")),
    [Res] = lists:foldl(fun rpn/2, [], Values),
    Res.

rpn(add, [X, Y|Stack]) ->
    [X + Y| Stack];
rpn(sub, [X, Y|Stack]) ->
    [X - Y| Stack];
rpn(mul, [X, Y|Stack]) ->
    [X * Y| Stack];
rpn(div, [X, Y|Stack]) ->
    [X / Y| Stack];
rpn(pow, [X, Y|Stack]) ->
    [math:pow(X, Y)| Stack];
rpn(X, Stack) ->
    [X| Stack].

%% 実数として読めるか試して失敗したら整数として読む
%% 整数でもなかったらアトムにする
%% なんか美しくない
read(X) ->
    case string:to_float(X) of
	{error,no_float} ->
	    try list_to_integer(X) of
		Y -> Y
	    catch
		error:_ -> list_to_atom(X)
	    end;
	{F, _} -> F
    end.

楽しいコンパイルのお時間……んん?

シンタックスエラー……だと?

syntax error before: 'div'

これdivってatom予約語だからみたいなんですけど。もうちょっといいエラーメッセージはなかったんでしょうか。

書いてみて思ったこと

doctest欲しい。欲しいすぎる。もしかしたらある?かも?
エラーメッセージ読みなれるまではつまらないミスでぬおおおお!ってなる日々になりそう。