clara-rulesというライブラリがにわかに自分の中で話題になっていたのでさっとまとめてみた。
概要・特徴
- ルールエンジンの実装を提供するライブラリ
- ドメインの知識をコードから分離する
- clj/cljs両方で利用できる
- Javaからも自然に利用できる
- 作者本人による講演のビデオもある [1] [2]
- より最近の講演のビデオもある
ルール?エンジン?
- エキスパートシステムに出自がある
- プログラマーが足り無い状況で、ビジネスユーザーがプログラマーを介することなく問題を解決できることが魅力で一時期流行ったが限界があった
- clara-rulesは現実的にどのようなルールでもコードであるという視点で、ビジネスユーザーではなくプログラマーをターゲットにしている
解決できること
- 何かロジックがあったとして、関数の呼び出しとして表現すると、そのロジックが必要とする情報を渡す/受けとることを明示的に書く必要がある
- ロジックが求める情報が変化する→必然的にリファクタリングが必要になる
- ルールを介することで情報を渡す/受けとる記述をする必要が無くなる
session
- 状態を表現する
- insert/retractでファクトを追加したり取り消ししたりする
- factはClojureレコードのインスタンスで表現する
- fire-rulesでセッションに追加されたファクトに対してルールを適用する
- イミュータブルな値(insert操作を行うと新しいセッションが返ってくる。古いセッションもそのまま残っている)
- Clojureっぽい
- 事実スレッディングマクロで操作することを想定した作りになっている
- mk-session(Clojure only)
- 引数無しの場合現在のネームスペースにあるルールを適用する
- defsession(ルールがあるネームスペースを指定する)
defrule
マクロ
- ルールを記述するためのマクロ
- 右辺と左辺がある
-
=>
で区切られる
-
- 左辺には何らかの判定ロジックを記述する(複数記述できる)
- 右辺には判定がtruthyになった時に起こる事を記述する
- 副作用を起こせる
- 現在のセッションにファクトを追加することもできる
簡単な例
(defrecord Num [number])
(defrule is-two
[Num (= number 2)] => (println "Two!"))
(-> (mk-session)
(insert (Num 4)))
(fire-rules))
;;Two!
クエリ?
- 元気がある時に調べる!
- 編集リクエストも。。。?
その他雑感等
- 明記はされていないが、clara-rulesという作りたい物が先にあって、その実装にClojureを選んだという雰囲気を感じる
- 簡単な例だけだと嬉しさが分らないのでまだまだ学習する必要がある
- JavaScriptにはnools,Rubyにはwongiという物があるらしい
- 動的にルールを生成するのはサポートされていない雰囲気を感じた
- defruleにおいて、左辺の型のプロトコルメソッドを使えるかどうか疑問に思ったが、作者の方にslackで可能だと教えてもらえた
Thanks for the clarification ryanbrush!
(defprotocol IFoo
(test-foo [this]))
(deftype Foo []
IFoo
(test-foo [this] true))
(defrule is-foo
[Foo (test-foo this;;スコープ内で自動的に束縛されるシンボルっぽい
)]
=> (println "is a foo"))
(-> (mk-session)
(insert (Foo.))
(fire-rules))
;;is a foo