24

我正在测试我的新版本 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 标准?

4

3 回答 3

13

单例变量在 Prolog 中是无用的,很容易通过编辑错别字引入。

我欢迎这个警告,因为它可以很容易地发现这种常见的错误原因。

作为警告,您可以运行包含单例的代码,但这些最终假定的任何值都将丢失。

我不认为ISO标准(从未听说过ANSI)禁止此类变量。

你可以用这种方式重写你的例子

member(X, [Y|T]) :- X = Y ; member(X, T).

然后忘记单例。

于 2013-03-14T17:40:37.893 回答
11

你这里有一个错误:

member(X,[X|T]) :- member(X,T).

实际上在说什么(与你认为你在说什么相反)是,member/2如果 X 位于列表的头部出现在列表的尾部,则它成立。这个谓词只对列表开头的同一事物的前 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])

单例警告告诉你“你在这里为某些东西保留了一个名字,但你从来没有用那个名字来调用任何东西。” 当我收到这条消息并且它不是一个明显的错字时,我做的第一件事就是用 _ 替换名称,看看我的代码是否仍然有意义。如果没有,我有一个逻辑错误。如果是这样,那可能是不必要的。

于 2013-03-14T19:19:22.533 回答
7

您可以在SWI-Prolog FAQ的官方页面上阅读它

出现此警告的最常见情况是:

  1. 变量中的拼写错误
  2. 忘记使用/绑定变量

SWI 提出了一些忽略它的方法:

  1. 为此目的使用名为 _ 的匿名变量。
  2. 使用以 _ 开头的变量(如_T, _X),以避免警告并记录您忽略的内容。
  3. 如果您知道自己在做什么,则可以使用:- style_check(-singleton).,并且所有警告都应该消失。
于 2015-02-19T14:26:14.240 回答