Continuing from the previous article, let’s talk about clara-rulues, an expert system in Clojure. In Clara, the defquery and query functions are used to output the results of reasoning to the outside world. A sample is shown below
ns test01.rules
(:require [clara.rules :refer :all]))
(defrecord Stage [status txt])
(defrule rule1
[Stage (= status "start" )]
=>
(insert! (->Stage " step1" "this is start"))
(println "this is start"))
(defrule rule2
[Stage (= status "step1")]
=>
(insert! (->Stage "next step" "this is next"))
(println "this is next"))
(defrule rule3
[Stage (= status "next step")]
=>
(insert! (->Stage "last step" "this is last"))
(println "this is last"))
(defquery get-ans []
[?a <- Stage]) (defn show-ans [session] (query session get-ans)) (defn ask-ans [q] (println "pre:" q) (-> (mk-session 'test01.rules)
(insert (->Stage q nil))
(fire-rules)
(show-ans)))
(defn get-ans-from-rules [res]
(-> (:params res)
(ask-ans)
(first)
(:?a)
:txt
))
Set Stage as the state record, and specify three rules to be applied to them, rule1, rule2, and rule3, using the defrule function. Set up a function to get the results of these rules with the defquery function, and set up an external output function get-ans-from-rule. The following is a sample code that uses these functions to output to the web api.
(ns test01.server
(:require [test01.rules :as rule]
[ring.util.response :as r]
[ring.adapter.jetty :as server]
[compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]
[ring.middleware.cors :refer [wrap-cors]]
[ring.middleware.x-headers :refer [wrap-frame-options]]))
(defonce server (atom nil))
(defn ans-response [req]
(r/response (response-data (rule/get-ans-from-rules req ))))
;;route
(defroutes app-routes
(GET "/ans-response" [] ans-response)
(route/not-found "Not Found"))
(def app
(-> app-routes
wrap-json-body
wrap-json-response
(wrap-defaults site-defaults)
(wrap-cors :access-control-allow-origin [#".*"] :access-control-allow-methods [:get])))
;;servef
(defn start-server []
(when-not @server
(reset! server (server/run-jetty app {:port 3000 :join? false}))))
(defn stop-server []
(when @server
(.stop @server)
(reset! server nil)))
(defn restart-server []
(when @server
(stop-server)
(start-server)))
(defn -main []
(start-server))
(start-server)
(stop-server)
(restart-server)
コメント