2

我正在尝试创建一个谓词,如果第三个列表由TF值组成,则该谓词为真,这取决于第一个和第二个列表中相同索引的两个元素是否相等的事实。像这样的查询truth_list(['abc','def'],['zui','def'],L).应该给出L=['F','T'].

这是我的尝试:

truth_list([],[],_).
truth_list([H1|T1],[H2|T2],TL):-
    (H1==H2)->(H3='T');(H3='F'),
    Temp=TL,
    TL=[H3|Temp],
    truth_list(T1,T2,TL).

如果有人能解释为什么这不能按预期工作,我将不胜感激。

4

2 回答 2

2

所以我们都在同一个页面上,当我运行查询时,我得到了这个结果:

L = ['F'|L].

所以首先想到的是您可能正在重用一个变量,实际上,以下子句看起来很可疑:

Temp=TL,
TL=[H3|Temp],

Prolog 中的变量并不像其他语言那样真正“可赋值”。你真正能做的就是建立一个绑定,所以上面的代码就是这样说的:

TL=[H3|TL]

这就是为什么我们的结果看起来像这样:L=['F'|L]。我稍微重写了正文以解决问题并使用以下代码结束:

truth_list([H1|T1],[H2|T2],[H3|TL]):-
    (H1=H2 -> H3='T' ; H3='F'),
    truth_list(T1,T2,TL).

你需要在整个条件周围加上括号,否则你会得到奇怪的行为。从那里,我刚刚删除了不必要的TL绑定(它们无论如何都不能工作,因为 Prolog 中的变量不是可赋值的)。事实证明,一旦你解决了这些问题,你会发现另一个问题,那就是你会得到这个:

L = ['F', 'T'|_G297].

如果不明显,这是因为您的基本情况太模糊,应该看起来像这样:

truth_list([], [], []).

所以最终修正后的版本是这样的:

truth_list([],[],[]).
truth_list([H1|T1],[H2|T2],[H3|TL]):-
    (H1=H2 -> H3='T' ; H3='F'),
    truth_list(T1,T2,TL).

这通常是@false 出现并指出我们在使用具有不同实例化的谓词时遇到问题的地方,所以让我们现在检查一下并避免一些愤怒:

?- truth_list(['abc','def'],['zui','def'],['T','F']).
false.
?- truth_list(['abc','def'],['zui','def'],['F','T']).
true.
?- truth_list(['abc','def'],['zui','def'],['F','T','T']).
false.
?- truth_list(['abc','def'],['zui','def','def'],['F','T','T']).
false.

这些看起来都很好,所以当所有的参数都被实例化时,看起来我们并不是在幻觉谎言。那挺好的。现在让我们检查部分实例化:

?- truth_list([X, 'def'], ['abc', Y], ['T', 'T']).
X = abc,
Y = def.

酷,这工作。

?- truth_list([X, 'def'], ['abc', Y], ['F', 'T']).
false.

嗯。好吧,看起来 Prolog 不知道为该'F'值幻觉其他一些绑定。不确定这是否是一个问题,但我没有看到明显的解决方案。这意味着以下可能不起作用:

?- truth_list(X, Y, ['T', 'T']).
X = Y, Y = [_G296, _G302].

令人惊讶,但它确实有效,分配给两个未知数的相同列表。凉爽的。我认为我们的状态很好。

编辑:让我们结合@false 的改进。然后我们得到以下信息:

truth_list([], [], []).
truth_list([H1|T1], [H2|T2], [H3|TL]) :-
  (H1 = H2, H3 = 'T' ; dif(H1,H2), H3 = 'F'),
  truth_list(T1, T2, TL).

现在我们得到了想要的行为:

?- truth_list([X, 'def'], ['abc', Y], ['F', 'T']).
Y = def,
dif(X, abc) ;

所以 Prolog 已经推断出 Y 是 'def',并得出结论 X 至少不是 'abc',所以这是一个改进。

于 2013-01-20T06:10:27.360 回答
2

maplist/4 可以简化您的代码:

truth_list(A, B, C) :-
  maplist(truth_, A, B, C).
truth_(A, B, C) :-
  A == B -> C = 'T' ; C = 'F'.

您还可以考虑增强您的代码以便(最终)重用。

代替任意常量 'T','F' 您可以使用可调用谓词如trueandfalse10获取可直接用于 CLP(FD) 的表达式

于 2013-01-20T08:40:32.953 回答