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

GNU Prolog中member谓词实现疑问:与《Prolog编程艺术》的差异

Prolog代码运行疑问与差异解析

问题背景

我用《Prolog编程艺术》里的代码在GNU Prolog中运行时遇到问题,原代码及运行警告如下:

mem(X,[X|Xs]).
% user:2: warning: singleton variables [Xs] for mem/2
mem(X,[Y|Ys]) :- mem(X,Ys).
% user:3: warning: singleton variables [Y] for mem/2

测试查询时出现错误:

| ?- mem(g, [a, g, e]).
uncaught exception: error(existence_error(procedure,mem/2),top_level/0)

我理解单例变量是仅使用一次的变量,于是修改代码解决了警告:

mem(X, [X|_]).
mem(X, [_|Ys]) :- mem(X, Ys).

修改后查询结果:

| ?- mem(b, [a, b, c]).
true

| ?- mem(d, [a, b, c]).
no

疑问

  1. 为什么第二个查询返回no而非false?
  2. 为何GNU Prolog与《Prolog编程艺术》中的示例存在差异?是Prolog标准变化导致的吗?

解答

1. 关于返回no而非false的原因

这就是不同Prolog实现的输出习惯差异,意思完全相同:都表示当前查询找不到符合条件的解。

  • GNU Prolog、部分SWI-Prolog交互模式里,查询失败就输出no;
  • 有些Prolog环境会输出false,只是控制台显示的字符串不同,逻辑上没有任何区别。

2. GNU Prolog与书中示例的差异原因

(1)单例变量警告

书中代码出现警告,是因为当年的Prolog实现对单例变量的检查没那么严,而现代GNU Prolog默认开启了严格检测——它会提醒你代码里存在只用过一次的变量,这类变量要么是笔误,要么可以用匿名变量_代替(就像你修改后的代码那样)。这不是Prolog标准变了,只是不同实现的默认配置不一样。

(2)existence_error(procedure,mem/2)错误

这个错误说明GNU Prolog没找到mem/2这个谓词,大概率是你输入原代码时没正确加载(比如输入到一半中断、没把两行代码都提交给解释器),和代码逻辑本身无关。你修改后的代码能正常运行,也能证明这一点。

(3)代码写法差异

书中用Xs、Y作为单例变量,现代Prolog推荐用_,这是代码风格的优化,不是语法标准的变化——早年Prolog允许单例变量存在,只是现代实现会通过警告帮开发者避免潜在错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:09:50