Android/Kotlin中使用CLIPS4android获取规则执行输出的方法问询
在Android/Kotlin中获取CLIPS4Android的执行输出
嘿,作为CLIPS新手在Android项目里用CLIPS4Android,确实得搞清楚怎么捕获规则执行后的输出。结合你给出的RulesTest类,我给你分享几种实用的方法:
方法1:通过clips.eval()查询结果
CLIPS的eval()方法可以执行CLIPS命令并返回字符串结果,你可以在run()方法执行完规则后,用它来查询facts、agenda或者自定义的查询语句,从而获取输出。
修改你的run()方法如下:
fun run(): String? { try { // 执行前先查看初始facts(可选) Log.d(tag, "初始facts: ${clips.eval("(facts)")}") // 运行规则 clips.run() // 执行后查询结果,这里以查询所有facts为例,你可以换成自己需要的CLIPS命令 val executionResult = clips.eval("(facts)") Log.d(tag, "规则执行后facts: $executionResult") return executionResult } catch (e: CLIPSError) { Log.e(tag, "执行CLIPS命令出错: ${e.message}") return null } }
这种方法最适合获取CLIPS内置命令的输出,比如查看当前事实库、议程中的规则等。
方法2:重定向CLIPS的标准输出
如果你的CLIPS规则里用了(printout stdout "内容")这样的语句输出信息,默认这些内容会到控制台,但在Android里我们可以通过自定义Router来捕获这些输出。
在你的RulesTest的init块中添加路由配置:
init { clips = Environment() clips.load(filepath) Log.d(tag, "Loading .clp...\n\n") // 配置自定义路由,捕获stdout输出 clips.setRouter("stdout", object : Router() { override fun print(str: String) { // 这里捕获到CLIPS规则中printout的内容 Log.d(tag, "CLIPS规则输出: $str") // 你可以把str存储到成员变量中,比如: // this@RulesTest.outputBuffer.append(str) } override fun println(str: String) { print(str + "\n") } override fun query(str: String): Boolean { return false // 不需要交互输入,返回false即可 } }) clips.reset() }
这样只要CLIPS规则里有printout的输出,都会被这个Router捕获,你可以直接打印到Log或者存到缓冲区供后续使用。
方法3:通过全局变量传递结果
如果你的规则需要返回结构化的处理结果,可以在CLIPS中定义全局变量,规则执行时给全局变量赋值,再在Kotlin中通过eval()获取这个变量的值。
第一步:在CLIPS规则文件中定义全局变量
; 定义全局变量存储结果 (defglobal ?*processingResult* = "") ; 示例规则 (defrule process-product (Product (productId ?pid) (quantity ?qty)) => ; 处理逻辑后给全局变量赋值 (bind ?*processingResult* (str-cat "处理产品ID: " ?pid " 数量: " ?qty)) )
第二步:在Kotlin中获取全局变量
修改run()方法:
fun run(): String? { try { clips.run() // 获取CLIPS全局变量的值 val result = clips.eval("?*processingResult*") Log.d(tag, "规则处理结果: $result") return result } catch (e: CLIPSError) { Log.e(tag, "获取结果失败: ${e.message}") return null } }
这种方法适合传递自定义的业务结果,把规则处理后的信息通过全局变量传递到Kotlin代码中。
结合你的代码的完整示例
这里整合了方法2和方法3的RulesTest类:
class RulesTest(filepath: String?) { private val clips: Environment private val outputBuffer = StringBuilder() // 存储CLIPS输出的缓冲区 fun stop() { clips.destroy() } @Throws(CLIPSError::class) fun assertItems(products: List<Item>) { for (product in products) { val insertItem = "(Product " + "(productId ${product.ProductId})" + "(uomid ${product.UOMId})" + "(quantity ${product.Quantity}))" Log.d(tag, "插入事实: $insertItem") clips.assertString(insertItem) } } fun run(): String? { return try { clips.run() // 获取全局变量结果 val globalResult = clips.eval("?*processingResult*") // 同时可以获取缓冲区的输出 Log.d(tag, "CLIPS输出汇总: ${outputBuffer.toString()}") globalResult } catch (e: CLIPSError) { Log.e(tag, "执行出错: ${e.message}") null } } companion object { const val tag = "CLIPSProductRulesTest" } init { clips = Environment() clips.load(filepath) Log.d(tag, "Loading .clp...\n\n") // 设置输出路由 clips.setRouter("stdout", object : Router() { override fun print(str: String) { outputBuffer.append(str) Log.d(tag, "CLIPS输出: $str") } override fun println(str: String) { print(str + "\n") } override fun query(str: String): Boolean { return false } }) clips.reset() } }
根据你的需求选择合适的方法就好啦,如果是看事实变化用方法1,捕获规则里的打印用方法2,传递业务结果用方法3~
内容的提问来源于stack exchange,提问作者NishaL
相关产品推荐
相关产品推荐

