如何在CLIPS的defrule中定义全局变量并在其他defrule中使用?
这个报错的原因很明确:deffacts是CLIPS启动时就会被断言的静态事实集合,而你在deffacts data里引用的?number1和?number2是rule1运行时才绑定的局部变量——局部变量只能在定义它的规则/函数内部生效,deffacts根本访问不到它们,而且初始化时这些变量还没被创建,自然会报错。
下面给你两种解决思路,其中第二种是更符合CLIPS设计范式的推荐方案:
方案1:使用全局变量(defglobal)
全局变量在CLIPS里以?*变量名*的格式定义,能在任何规则、函数中访问。具体步骤如下:
- 先提前定义全局变量并初始化;
- 在
rule1中把输入的值绑定到全局变量上; - 后续其他规则就能直接调用这些全局变量。
修改后的代码示例:
(defglobal ?*number1* = 0 ?*number2* = 0) ; 初始化全局变量 (deffunction calculation1 (?x ?y) (+ ?x ?y)) (defrule rule1 => (printout t "What is the first number?") (bind ?*number1* (read)) ; 绑定到全局变量 (assert (number-1 ?*number1*)) (printout t "What is the second number?") (bind ?*number2* (read)) ; 绑定到全局变量 (assert (number-2 ?*number2*)) (bind ?theirsum (calculation1 ?*number1* ?*number2*)) (printout t "The sum is " ?theirsum crlf) ) ; 示例:另一个规则调用全局变量 (defrule rule2 => (printout t "Stored number1: " ?*number1* crlf) (printout t "Stored number2: " ?*number2* crlf) )
⚠️ 注意:全局变量虽然能解决问题,但在CLIPS中不建议过度使用——规则引擎的核心是基于事实的状态管理,全局变量会让状态变得不透明,增加调试难度。
方案2:用事实共享数据(推荐的CLIPS范式)
你其实已经在rule1里做了正确的事:断言了(number-1 ?number1)和(number-2 ?number2)这两个动态事实。其他规则只需要通过匹配这些事实就能获取对应的值,这才是CLIPS设计的正确用法,完全不需要全局变量。
比如,如果你想写一个规则来复用这两个数字,代码可以这样写:
(deffunction calculation1 (?x ?y) (+ ?x ?y)) (defrule rule1 => (printout t "What is the first number?") (bind ?number1 (read)) (assert (number-1 ?number1)) (printout t "What is the second number?") (bind ?number2 (read)) (assert (number-2 ?number2)) (bind ?theirsum (calculation1 ?number1 ?number2)) (printout t "The sum is " ?theirsum crlf) ) ; 另一个规则,通过匹配事实获取数字并使用 (defrule use-stored-numbers (number-1 ?num1) (number-2 ?num2) => (printout t "Using input numbers: " ?num1 " and " ?num2 crlf) (bind ?product (* ?num1 ?num2)) (printout t "Their product is " ?product crlf) )
解释:当rule1运行并断言了number-1和number-2事实后,use-stored-numbers规则会自动被激活,匹配这两个事实并将值绑定到?num1和?num2变量中,这样就能在规则里直接使用它们了。
另外你原来的deffacts data完全不需要保留——因为这两个数字是用户动态输入的,不是静态的初始事实,用assert在规则里动态添加事实才是正确的方式。
内容的提问来源于stack exchange,提问作者user2018
相关产品推荐
相关产品推荐

