2013年12月2日月曜日

Ruby-Prologについてのメモ

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"]のようにシンボル以外の引数を渡したときには引数がそのまま戻ってくる。