prolog 中的单例变量

问题描述 投票:0回答:4

我正在测试我的新版本的 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
4个回答
14
投票

单例变量在 Prolog 中是无用,并且可以通过编辑拼写错误轻松引入。

我欢迎警告,因为它可以轻松发现这种常见的错误原因。

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

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

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

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

然后忘记单例。


11
投票

你这里有一个错误:

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])
的真实性无关。

单例警告告诉您“您已为此处的某些内容保留了一个名称,但您从未用该名称调用任何内容。”当我收到这条消息并且这不是一个明显的拼写错误时,我做的第一件事就是用 _ 替换名称,看看我的代码是否仍然有意义。如果没有,我就有逻辑错误了。如果是的话,可能就没有必要了。


9
投票

您可以在SWI-Prolog FAQ

的官方页面上阅读相关内容

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

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

SWI 建议一些忽略它的方法:

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

0
投票

这是《立即学习 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,_))).

谢谢大家。

© www.soinside.com 2019 - 2024. All rights reserved.