Prologをほとんど知らない私がRuby-Prologを使ってみたメモ。
まずは基本的な使い方。
require "ruby-prolog"
c = RubyProlog::Core.new
c.parent["Ieyasu", "Hidetada"].fact
c.parent["Hidetada", "Iemitsu"].fact
c.grandpa[:X, :Y] << [c.parent[:X, :Z], c.parent[:Z, :Y]]
p c.query(c.grandpa[:X, :Y])
#=> [[grandpa["Ieyasu", "Iemitsu"]]
いちいちc.って書くのが面倒なときはinstance_evalを利用する。irbで試すときはc.ってつけて一行ずつ処理した方が分かりやすい。
c.instance_eval do
parent["Ieyasu", "Hidetada"].fact
parent["Hidetada", "Iemitsu"].fact
grandpa[:X, :Y] << [parent[:X, :Z], parent[:Z, :Y]]
query grandpa[:X, :Y]
end
queryメソッドは内部的にresolveメソッドを呼び出している。resolveメソッドの挙動について調べる。
c.resolve(c.parent[:X, :Y]){|env| p env[:X]}
#=> "Hidetada"
"Iemitsu"
c.resolve(c.parent[:X, :Y]){|env| p env["Ieyasu"]}
#=> "Ieyasu"
"Ieyasu"
c.resolve(c.parent[:X, "Iemitsu"]){|env| p env[:X]}
#=> "Hidetada"
c.resolve(c.grandpa[:X, "Iemitsu"]){|env| p env[:X]}
#=> "Ieyasu"
要するに、与えた式が成り立つ状況をリストアップしてブロックを実行する。状況はenvという変数でブロックに渡され、env[:X]のようにしてその状況における変数:Xの値を調べることができる。env["Ieyasu"]のようにシンボル以外の引数を渡したときには引数がそのまま戻ってくる。