Prolog 写経記 その 1 append/3

どうせなら写経と日記を組み合わせてしまいましょう.
これなら継続しやすいし日記のネタにもなって一石二鳥♪
写経するのは昨日も紹介したこの本.

Prologユーティリティライブラリ

Prologユーティリティライブラリ

これに出てくる述語を (ほぼ) 毎日一つずつ写経していきます.3〜4か月で写経し終えるはず.
本来はもっとスピード感が必要な気もするわけですが,歳も歳だし (?) 気にしない気にしない.
ほんたった」がないことも気にしない気にしない...


ともあれ (JW),初回の今日は昨日の紹介と被りますが append/3 です.
この append/3 という書き方は,述語の名前が append で,引数の数 (arity) が 3 であることを示しています.いわゆるシグネチャProlog は型付けの弱い言語なので,引数の型は関係なく数だけが重要なのですね.

解説

append/3 が何をするかというと

append(X, List1, List2) は要素 XList1 の先頭に付け加えた新しいリストを List2 として返す.

ということです.JavaLinkedList#addFirst(Object) 相当ですね.

モード

モードというのは引数が入力になる (+) か出力になる (-) か,あるいはどちらにもなり得るのか (?) を示します.
append/3 の場合は

append(?, ?, ?)

ということで,いずれの引数も入力または出力に使うことができます.

定義

では,こいつの定義を写経しませう.

append(X, List, [X|List]).

これだけ.
定義というより宣言にしか見えませんが,これでも立派な述語の定義.こいつの場合,述語の頭部しかないのですが,明日は述語の本体を持つものが出てきます.頭部しかない述語は「事実」を,頭部と本体を持つ述語は「規則」を表現するそうな.
ともあれ (JW),この述語は引数を 3 つ取ります.最初の二つは問題ないとして,第 3 引数はちょっと見慣れない形をしています.
この

[X|List]

という表記は全体としてこれがリストであることを示しています.そしてその最初の要素が X,残りの要素からなるリストが List であることを示しています.
例えば [1, 2, 3, 4, 5] というリストを [X|List] に当てはめた場合は,

  • X1
  • List[2, 3, 4, 5]

となります.逆に言うと,X1List[2, 3, 4, 5] の場合,[X|List][1, 2, 3, 4, 5] になるということです.Lisp の car,cdr, cons 相当ですね.


で,append/3 という述語の定義は,第 1 引数を最初の要素,第 2 引数が残りの要素のリストであるようなリストが第 3 引数であるという事実を定めているということになります.たぶん.
このように,Prolog の述語は引数の間に成り立つ関係を定めたものになります.

では,実際の使用例を写経しませう.

2 ?- append(john, [mary, tom, ann], L).

L = [john, mary, tom, ann] ;

No
3 ?- append(X, Y, [23, 14, 77, 6]).

X = 23
Y = [14, 77, 6] ;

No
4 ?- append('A', ['C', 'B'], ['C', 'B', 'A']).

No
5 ?- 

数字の後ろに ?- とあるのはプロンプトです.その後ろが実際に入力した内容.
なので,最初の使用例は

append(john, [mary, tom, ann], L).

john という要素を [mary, tom, ann] というリストの先頭に付け加えたリストを L (変数)としたらどうよ? という意味.
Prolog では大文字で始まると変数,小文字で始まるとアトムと呼ばれるリテラルになるようです.あと数値リテラルも使えます.
ともあれ (JW),このように質問すると Prolog

L = [john, mary, tom, ann] ;

と答えてくれます.
最後の ';' は他にも答があるか探してもらうために入力したもの.それが見つからなければ

No

と冷たい答が返ってきます.
次の使用例は

append(X, Y, [23, 14, 77, 6]).

これは先の使用例とは使い方が異なり,X という要素を Y というリストの先頭に付け加えると [23, 14, 77, 6] というリストになるけどどうよ? という意味.
さっきは第 1 引数と第 2 引数に具体的な値を与えて結果を第 3 引数として答えてもらいましたが,今度はそれが逆になっています.これが Prolog の面白いところ.上の「モード」はこれを表していた次第.
ともあれ (JW),このように質問すると Prolog

X = 23
Y = [14, 77, 6] ;

No

と答えてくれます.
最後の使用例は,3 引数全てに具体的な値を渡しています.

append('A', ['C', 'B'], ['C', 'B', 'A']).

この場合は,変数に該当する値を返してくれるのではなく,与えた引数が述語の定義にマッチするかを答えてくれます.'A' という要素を ['C', 'B'] というリストの先頭に付け加えると ['C', 'B', 'A'] になるけどどうよ? ってこと.
この場合の結果は当然

No

です.
次のように正しい質問をすると

5 ?- append('A', ['B', 'C'], ['A', 'B', 'C']).

Yes

と答えてくれます.
ちなみに 'A' みたいに引用符で囲むと大文字から始まるアトムを表すことができます.


と,こんな感じで淡々と写経する (ほぼ) 毎日を送っていこうかな,と思う次第.
ふぅ,これで一応技術ネタのない日記を返上できるかな♪
相変わらず Java ネタはないってことにないますが.心より恥じる.