2007-10-12

Prolog (3)

簡易電卓を作成するとき、優先括弧に"(",")"という表記を使いました。実はPrologの仕様で(,)と.は自由なアトムとして使うことが出来ないからです。ところで、このダブルクオーテーションで囲んだ表記法ですが、一般的な言語では文字列リテラルと解釈されます。しかしPrologでは厳密な文字列型というオブジェクトは存在しません。一見文字列のようなこの値は、述語名や定数などと同様、小文字から始まるアトム型で、その別表記に過ぎません。同時に、データ上は数値リストとして扱うことが可能です。

リスト中に文字と数字が並ぶ際には上記の事を注意しなければいけません。

?- [X] = "(".
X = 40 ;
No

というように、リスト要素をマッチングして行くと思わぬところで単一化されてしまいます。これを除こうと思っても、実際に数値なのでnumber/1は使えません。但し[X]全体をマッチしてやればnumber/1はfalseとなります。

アトムの文字列表記が数値リスト(ASCII値となります)であることを利用して、シーザー暗号を作ってみましょう。変換部分はそのままです。

translate([], []).
translate([X|R], [X1|R1]) :-
plus(X, 3, X1),
translate(R, R1).


アトムとその文字列表記の変換にはatom_codes/2を利用します。他にもchar_code/2やnumber_codes/2などが仕様にあります。ちなみにこの述語の引数をどちらも変数にすると例外が発生しますから、暗号のエントリ述語はこんな風に書きました。

caesar(Flat, Unflat) :-
((nonvar(Flat),
atom_codes(Flat, C1));
(nonvar(Unflat),
atom_codes(Unflat, C2))),
translate(C1, C2),
atom_codes(Flat, C1),
atom_codes(Unflat, C2).

平文も暗号文も可逆入力ですが、なんだかちょっと冗長ですね :)

0 件のコメント: