人工無能を書いてみる

lisp on yarvでマクロが使えるようになったので、そろそろ何かプログラム書いて
みようということで、「恋するプログラム—Rubyでつくる人工無脳」という本を参考に、人工無能を書いていこうと思います。

この本には、いろいろと思い入れがあります。はじめて自分で作ったと言えるようなプログラムは、この本を参考にして、javaで作った人工無能です。
この本がなかったらプログラム書けるようにならなかったと思います。

それから、Lispの処理系を作り始めたきっかけのひとつは、自分で作った人工無能Lispで書き直してみたいと思ったことです。
いつのまにか処理系を作るのが目的になり、この3年間まったく人工無能は書いていなかったので、いい機会なので人工無能を書いてみようと思います。

とりあえず一番単純なものを書いてみました。

(defclass Responder
  (def (initialize name)
    (= @name name))

  (def (response input)
       (+ input "ってなに?"))
  (def (name)
       @name))

(defclass Unmo
  (def (initialize name)
    (= @name name)
    (= @responder (Responder.new "What")))

  (def (dialogue input)
       (@responder.response input))

  (def (responder_name)
       (@responder.name))
  (def (name)
       @name))

(def (prompt unmo)
     (+ unmo.name ":" unmo.responder_name "> "))

(puts "Unmo System prototype : proto")
(= proto (Unmo.new "proto"))

(loop 
   (block ()
	  (print "> ")
	  (= input (gets.chomp!))
	  (if (== input "")
		 break)
	     (puts (+ (prompt proto) (proto.dialogue input)))))

defclassはこんな感じのマクロで定義しています。

(macro (defclass x *body)
       `(begin
	 (rasm "class ")
	 ,x
	 ,@(a2l body) ;a2lはrubyの配列をlistに変換する関数
	 (rasm "end\n")))
;例
(defclass Test
  (def (test a)
    (puts a)))

;=> コンパイル結果
; class Test
;  def test(a)
;    puts a
;  end
; end

書いてて思ったのですが、lispの処理系を作ったというよりは、S式でRubyが書ける処理系を作ったって感じです。