我正在测试我的新版本的 SWI prolog,并不断遇到错误:单例变量。
示例:
member(X,[X|T]).
member(X,[X|T]) :- member(X,T).
查找列表中的成员,例如:
member(yolands,[yolanda,tim])
X = yes
但是我得到了 X 和 T 单变量错误
如果我执行以下操作:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
它有效,但看起来很丑!
谁能解释一下为什么不允许使用单个变量以及是否符合 ANSI 标准?
单例变量在 Prolog 中是无用,并且可以通过编辑拼写错误轻松引入。
我欢迎警告,因为它可以轻松发现这种常见的错误原因。
作为警告,您可以运行包含单例的代码,但这些最终假设的任何值都将丢失。
我不认为ISO标准(从未听说过ANSI)禁止此类变量。
你可以用这种方式重写你的例子
member(X, [Y|T]) :- X = Y ; member(X, T).
然后忘记单例。
你这里有一个错误:
member(X,[X|T]) :- member(X,T).
您实际上所说的(与您认为自己所说的相反)是,如果X位于列表的头部
且位于列表的尾部,则
member/2
成立。这个谓词只对列表开头的同一事物的前 N 个副本为真,所以这是一件非常奇怪的事情!
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
现在,您可以通过执行以下操作来纠正错误并仍然收到单例警告:
member(X, [Y|T]) :- member(X, T).
但这不如具有两个头的传统定义或带有显式 OR 的 @CapelliC 版本 (+1)。我认为你应该等到你对 Prolog 有了更好的了解之后,再对 Prolog 代码的美感投入更多的精力。如果你坚持一段时间,你就会欣赏这个警告以及匿名变量的使用。
单例变量在 Prolog 中无用的原因是它们被命名了,但对它们一无所知,并且它们对其余计算没有影响。下划线强调绝对任何东西都可以放入其中而不影响含义。是什么让
member(X, [X|T]).
true 是,位置 1 的 X 与位置 2 列表头部的 X 相同。列表必须为空或有头和尾,但尾部的内容在这里并不相关,重要的是是X也是头。 T 可能是列表的其余部分,也可能是不正确的列表,也可能是面包箱、闪电或春日空气中的气味。它与
member(X, [X|T])
的真实性无关。
单例警告告诉您“您已为此处的某些内容保留了一个名称,但您从未用该名称调用任何内容。”当我收到这条消息并且这不是一个明显的拼写错误时,我做的第一件事就是用 _ 替换名称,看看我的代码是否仍然有意义。如果没有,我就有逻辑错误了。如果是的话,可能就没有必要了。
您可以在SWI-Prolog FAQ
的官方页面上阅读相关内容出现此警告的最常见情况是:
SWI 建议一些忽略它的方法:
_T
、_X
),以避免警告并记录您忽略的内容。:- style_check(-singleton).
,所有警告都会消失。 这是《立即学习 Prolog》中的示例! (第 31 页)。它产生了错误消息“单例变量:...”
vertical(line(point(X,Y),point(X,Z))).
horizontal(line(point(X,Y),point(Z,Y))).
用匿名变量_替换垂直/1中的X和水平/1中的Y,消除了错误消息。
vertical(line(point(_,Y),point(_,Z))).
horizontal(line(point(X,_),point(Z,_))).
谢谢大家。