Prolog执行verificar相关代码时触发si(A)过程不存在错误
报错成因
- 触发该报错的核心原因是Prolog引擎的谓词存在性校验机制:默认情况下引擎会对所有被调用的谓词做静态检查,如果某谓词既没有在源码中做显式定义,也没有提前声明为可动态修改的谓词,运行时一旦尝试查询该谓词,就会抛出
procedure 'xxx' does not exist的错误提示。 - 对应代码中,
si/1、no/1是用于存储用户问诊回答的动态事实库:只有当用户针对某个症状给出“是/否”的明确答复后,才会通过assert/1在运行时往数据库中插入对应的事实。但全程没有对这两个谓词做动态声明,导致执行流走到verificar(S)分支首次尝试查询si(S)时,引擎根本无法识别这个未注册的谓词,直接中断执行抛出错误。从报错给出的可达调用链evaluar -> hipotesis(A) -> resfriado -> verificar(A)也可佐证,此时si(A)的查询发生在任何动态事实插入之前,完全没有对应的谓词定义存在。
解决方案
- 在所有谓词定义的最开头,添加全局动态谓词声明,明确告知Prolog引擎这两个谓词支持运行时动态增删事实,无需提前做静态存在性校验,声明语句为:
:- dynamic si/1, no/1. - 需确保动态声明是全局位置的语句,不要写在某个业务谓词的内部,避免声明作用域不生效。
- 修复完成后的核心代码可参考如下写法:
% 全局声明动态存储的事实谓词 :- dynamic si/1, no/1. verificar(S) :- (si(S) -> true ; (no(S) -> fail ; preguntar(S))). preguntar(Pregunta) :- write('Tiene los siguientes sintomas: '), write(Pregunta), write('?'), read(Respuesta), nl, ( (Respuesta == si) -> assert(si(Pregunta)); assert(no(Pregunta)), fail). - 版本兼容提示:如果使用的是早期版本的Prolog解释器,动态声明的语法可能存在细微差异,可根据对应解释器的文档调整声明格式(如部分老版本需要写为
:- dynamic(si/1), dynamic(no/1).)。
内容的提问来源于stack exchange,提问作者natalie85
相关产品推荐
相关产品推荐

