prolog中的单例变量

Tim*_*man 21 prolog

我正在测试我的新版SWI prolog并不断遇到错误:singleton变量.

例:

member(X,[X|T]).

member(X,[X|T]) :- member(X,T).
Run Code Online (Sandbox Code Playgroud)

找到列表的成员,例如:

member(yolands,[yolanda,tim])

X = yes
Run Code Online (Sandbox Code Playgroud)

但相反,我得到X和T 的单例变量错误

如果我做以下事情:

member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
Run Code Online (Sandbox Code Playgroud)

它有效,但看起来很难看!

任何人都可以解释为什么允许单个变量和这个ANSI标准吗?

Cap*_*liC 15

单例变量在Prolog中是无用的,并且通过编辑拼写错误很容易引入.

我很欢迎这个警告,因为它可以轻松发现这种频繁的错误原因.

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

我不认为ISO标准(从未听说过ANSI)禁止这样的变量.

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

member(X, [Y|T]) :- X = Y ; member(X, T).
Run Code Online (Sandbox Code Playgroud)

然后忘记了单身人士.


Dan*_*ons 10

你有一个错误:

member(X,[X|T]) :- member(X,T).
Run Code Online (Sandbox Code Playgroud)

实际上说的什么(与你认为你所说的相反)是,member/2如果X位于列表的头部出现在列表的尾部,那就是成立.这个谓词只会在列表开头的同一件事的前N个副本中成立,所以这是一个非常奇怪的事情!

?- member(X, [a,a,c]).
X = a ;
X = a ;
false.

?- member(X, [b,a,a]).
X = b ;
false.
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过执行以下操作来纠正错误并仍然有单例警告:

member(X, [Y|T]) :- member(X, T).
Run Code Online (Sandbox Code Playgroud)

但这不如传统的两个头的定义或@ CapelliC的版本(+1)具有明确的OR.我认为你应该等到你更好地了解Prolog之后才能在Prolog代码美学方面投入大量资金.如果你坚持一段时间,你会发现这个警告以及匿名变量的使用.

使单例变量在Prolog中无用的原因是它们被命名,但对它们一无所知,它们对其余的计算没有影响.下划线强调,在不影响含义的情况下,绝对可以进行任何事情.是什么使得

member(X, [X|T]).
Run Code Online (Sandbox Code Playgroud)

是的,X是位置1与位置2列表头部的X相同.列表必须是空的或者有头部和尾部,但尾部的内容与此处无关,重要的是X也是头.T可能是列表的其余部分,或者它可能是一个不正确的列表,或者它可能是一个面包箱或闪电或春天的空气气味.它与事实无关member(X, [X|T]).

单身警告告诉你"你在这里保留了一个名字,但是你永远不会用这个名字来称呼任何东西." 当我收到此消息时,我做的第一件事就是用_替换名称并查看我的代码是否仍然有意义.如果没有,我有一个逻辑错误.如果是这样,那可能就没必要了.


Ole*_*rov 7

您可以在SWI-Prolog FAQ的官方页面上阅读相关信息

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

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

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

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