You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Clojure的Clara Rules中更新事实?

问题分析与解决方案

你的代码问题点

你提供的代码存在几个语法/用法错误,这是导致规则不工作的直接原因:

  • defrecord UserData 定义末尾缺少闭合括号 )
  • 规则中的箭头符号用了HTML转义的 &lt;/&gt;,需替换为Clara支持的 </>
  • 规则右侧操作(RHS)写法错误:你把retract!和insert!包在双重括号里,这会导致尝试调用retract!的返回值作为函数,正确做法是用do块包裹多个操作(或直接换行利用Clojure隐式do)
  • run-rules函数最后没有返回会话结果,无法获取更新后的状态

修正后的代码

(ns clara.rules.test
  (:require [clara.rules :refer :all]))

;; 补全UserData定义的闭合括号
(defrecord Users [#^ints user-ids])
(defrecord UserData [user-id dob age])

(defrule rule-1
  ;; 替换转义符号为正确的箭头
  [?ud <- UserData (> age 20)]
  [?u <- Users]
  =>
  ;; 用do块执行多个操作,去掉多余括号
  (do
    (retract! ?u)
    (insert! (->Users (conj (:user-ids ?u) (:user-id ?ud))))))

;; 保留自定义条件占位,实际使用时需实现some-condition逻辑
(defrule rule-2
  [?ud <- UserData (some-condition)]
  [?u <- Users]
  =>
  (do
    (retract! ?u)
    (insert! (->Users (conj (:user-ids ?u) (:user-id ?ud))))))

(defn run-rules
  [user-data]
  (let [res (-> (mk-session 'clara.rules.test)
                (insert (->UserData (:user-id user-data) (:dob user-data) (:age user-data))
                        (->Users []))
                (fire-rules))]
    ;; 返回会话,方便后续提取更新后的事实
    res))

核心问题解答

Clara Rules不支持直接更新现有事实,官方推荐的做法就是你尝试的「撤回旧事实 + 插入新事实」模式,这是规则引擎中处理状态更新的标准方式。

使用时需注意几个关键点:

  • 确保撤回的事实与插入的新事实是逻辑上的同一份状态,避免出现重复的Users事实
  • 若多个规则可能修改Users事实,可通过:salience参数调整规则触发优先级(默认按定义顺序触发)
  • 可通过查询验证更新结果,比如添加以下查询函数:
(defquery get-users
  []
  [?u <- Users])

;; 使用示例
(let [session (run-rules {:user-id 1 :dob "1999-01-01" :age 25})]
  (query session get-users))

内容的提问来源于stack exchange,提问作者xyj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:23:06