#:g1: cl-unificationの紹介

Posted 2014-12-17 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の352日目です。

cl-unificationとはなにか

 cl-unificationは、Marco Antoniotti氏作のCommon Lispでユニフィケーションを実現するライブラリです。

パッケージ情報

パッケージ名cl-unification
Quicklisp
CLiKiCLiki: cl-unification
Quickdocscl-unification | Quickdocs
common-lisp.netcl-unification
CL Test Grid: ビルド状況cl-unification | CL Test Grid

インストール方法

(ql:quickload :cl-unification)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 基本的な構造はシンプルで、ユニファイする変数と環境を指定するとマッチした結果が取得できます。

(unify 42 42)
;=>  #<EMPTY UNIFY ENVIRONMENT: 1 frame {101BFAA993}>

(let ((env (unify #T(number ?x) 42))) (find-variable-value '?x env)) ;=> 42 ; T

(let ((env (unify (list 1 '?y 3) (list '?x 2 '?z)))) (list (find-variable-value '?x env) (find-variable-value '?y env) (find-variable-value '?z env))) ;=> (1 2 3)

 マッチにはテンプレートを利用できて、複合したデータ構造もこれを指定すればマッチ可能です。

(let* ((env (unify #T(number ?x) 42))
       (env (unify #T(number ?y)
                   (find-variable-value '?x env)
                   env)))
  (list (find-variable-value '?x env)
        (find-variable-value '?y env)))
;=>  (42 42)

(defclass makanito () ((a :accessor a) (b :accessor b)))

(defvar *obj* (make-instance 'makanito))

(setf (a *obj*) 42 (b *obj*) 43)

(describe *obj*) ;>> #<MAKANITO {10203724D3}> ;>> [standard-object] ;>> ;>> Slots with :INSTANCE allocation: ;>> A = 42 ;>> B = 43 ;>> ;=> <no values>

(let ((env (unify #T(makanito a ?a b ?b) *obj*))) (list (v? '?a env) (v? '?b env))) ;=> (42 43)

#Tというのがテンプレート用のリーダーマクロでデータ型名とスロットを指定します。
また、expression-templateというものの場合、読み出し手続きの結果として値が返ってきます。

(let ((env (unify (*:iota 100) #T(elt 3 ?x))))
  (find-variable-value '?x env))
;=>  3
;    T

 さらに、制御構文としてパタンで分岐する各種matchがあります。

(defun h (op a b)
  (match-case ((list op a b))
    ('(+ 
       #T(number ?M)
       #T(number ?N))
     (+ M N))
    ('(+ 0 ?F)  F)
    ('(+ ?F 0)  F)
    ('(+ ?A (+ ?B ?C))  (h '+ (h '+ A B) C))
    ((list '*
           #T(number ?M)
           #T(number ?N))
     (* M N))
    ('(* 0 ?F)  0)
    ('(* ?F 0)  0)
    ('(* ?F 1)  F)
    ('(* 1 ?F)  F)
    ('(* ?A (* ?B ?C))  (h '* (h '* A B) C))
    ('(?Op ?A ?B)  (list Op A B))))

(defun harropify (x) (match-case (x) ('(?Op ?A ?B) (h Op (harropify A) (harropify B))) (?A A)))

(harropify '(* (+ 1 2) (+ (* x 0) y))) ;=> (* 3 Y)

まとめ

 今回は、cl-unificationを紹介してみました。
双方向マッチを使わないとあまり旨味がない気がしますが、テンプレートを拡張できるのは便利ですね。

comments powered by Disqus