#:g1: データの検索に組み込みPrologを使ってみる(3): オブジェクトデータベースと組み合わせる

Posted 2021-10-12 03:43:11 GMT

Allegro Prolog + AllegroCache 篇

PAIPrologで挑戦したところデータの登録に難があったので、その辺りの問題はクリアされていそうな、Allegro Prolog + AllegroCache で試してみたいと思います。

パッケージ定義/ユーティリティ等は前回のものを引き続き利用しています。

(require :acache "acache-3.0.8.fasl") ;環境ごとにバージョンが異なる
(require "pcache")
(require "prolog")

(defpackage covid19.mhlw.go.jp (:use cl fare-csv prolog db.allegrocache))

;;OODBのためのユーティリティ (defmacro with-file-database ((name &key (if-exists nil if-exists-p) (if-does-not-exist nil if-does-not-exist-p) read-only) &body body) `(let ((*allegrocache* nil)) (unwind-protect (multiple-value-prog1 (progn (open-file-database ,name ,@(and if-exists-p `(:if-exists ,if-exists)) ,@(and if-does-not-exist-p `(:if-does-not-exist ,if-does-not-exist))) ,@body) (unless ,read-only (commit))) (when *allegrocache* (close-database :db *allegrocache*)))))

;;節となるオブジェクト定義 (defclass covid19-newly-confirmed-cases-daily () (date prefecture cases) (:metaclass persistent-class))

;;データを登録 (with-file-database ("/tmp/covid19.db" :if-does-not-exist :create :if-exists :supersede) (dolist (row (cdr *newly_confirmed_cases_daily.csv*)) (let ((obj (make-instance 'covid19-newly-confirmed-cases-daily))) (with-slots (date prefecture cases) obj (setf (values date prefecture cases) (values (covid19-date row) (covid19-prefecture row) (covid19-cases row)))))))

;;愛知の2021年9月の合計 (with-file-database ("/tmp/covid19.db") (let ((sum 0)) (prolog (db covid19-newly-confirmed-cases-daily ?obj date (2021 9 ?) prefecture "Aichi" cases ?cases ) (lisp (incf sum ?cases))) sum)) → 21255

;;都道府県ごとの合計 (with-file-database ("/tmp/covid19.db") (let ((tab (make-hash-table :test #'equal))) (prolog (db covid19-newly-confirmed-cases-daily ?obj) (is ?pref (slot-value ?obj 'prefecture)) (is ?cases (slot-value ?obj 'cases)) (lisp (incf (gethash ?pref tab 0) ?cases))) (loop :for pref :being :the :hash-keys :of tab :using (:hash-value cases) :repeat 2 :collect (list pref cases))))(("Shizuoka" 26308) ("Shiga" 12388))

まとめ

Allegro PrologはPAIPrologから派生しただけに似た感じではありますが、AllegroCacheと連携することによってオブジェクトのクエリが可能になります。
今回の場合、永続化機能は必要ないのですが、Allegro Prologのdb述語を利用するにはpersistent-classと連携するほかないようです。
別途インスタンスプールにインスタンスを登録するメタクラスとdb述語のようなパタンマッチ述語を自作すれば、AllegroCacheを迂回することも可能かとは思います。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus