Prolog中Cut运算符的交换

时间:2017-04-22 21:31:51

标签: prolog prolog-cut

我正在学习Prolog,在我正在阅读的一个注释中给出了如何正确使用切割算子的例子。请考虑以下函数从列表中删除特定值的所有元素。

rm(_,[],[]).
rm(A,[A|L],R) :- rm(A,L,R).
rm(A,[B|L],[B|R]) :- rm(A,L,R).

由于回溯,这不是函数的正确定义,函数将返回从删除特定值的某些元素所获得的列表的所有子列表,但不一定全部返回。我正在阅读的笔记说,解决这个问题的正确方法是用行替换第二行

rm(A,[A|L],R) :- !, rm(A,L,R)

但是用

代替了这一行
rm(A,[A|L],R) :- rm(A,L,R), !

不正确。我不确定为什么第二个例子是修复函数​​的错误方法。在swipl中,用这些修复替换第二个术语似乎总是在我考虑的测试用例中返回相同的答案。我在这里缺少什么?

1 个答案:

答案 0 :(得分:5)

你的例子是一个很好的例子来说明为什么在这里使用剪切永远是一个好主意。

如果第一个和第二个参数都充分实例化,则使用var twitterpack = require('twitter'); var tokens { consumer_key: '-------9WJSaaqAe9yVvr30CF', consumer_secret: '-------------------fj3zoiZ2nUOTBWUjP4DqtGXIlzzbxbOY', token_key: ' ----------zNHmdL43N6RZJeOtJeH8ZhrursJUQlAqCycHqxbl', tokenk_secre: '----EcxAjUq1hLka2QYwSSZStETF7Mr2mBikHYCTTqodV' } var twitter = new twitterpack(tokens); Twitter.stream('statuses/filter', {track: 'hey'}, function(stream) { stream.on('data', function(stream){ console.log(tweet.text); var meanReply = {status: "hey @" + tweet.user.screen_name} Twitter.post('statuses/update', meanReply, function(error, tweetReply, response){ if(error) {console.log(error) /*&&db.collection('errors', error.text)*/}; console.log(tweetReply.text)} ); }); stream.on('error', function(error) { console.log(error); }); }); 才有意义。但是如果它们没有得到充分的实例化,那么你会得到一个不完整的答案:

rm(A,[A|L],R) :- !, rm(A,L,R).

这明显错过了一个答案,因为它只将?- rm(X, [a], R). X = a, R = []. % incomplete 限制为X。但如果a是其他任何东西,我们会得到不同的结果,即:

X

?- X = b, rm(X,[a],R). R = [a]. 中使用最后的剪切更加糟糕:首先,到目前为止我们所有的假设都必须保持,然后另外第三个参数不能被实例化。否则我们会得到其他不正确的解决方案。

rm(A,[A|L],R) :- rm(A,L,R), !.

回想一下我们在这里问的问题:

  

用户:从列表?- rm(a,[a],R). R = []. ?- rm(a,[a],[a]). true % incorrect 中删除a后,我们得到了什么?

     

Prolog:没什么,没有,nada。

     

用户:但我不能只有[a]而不是一无所有?请!

     

Prolog:好的,我放弃了。

这不是您想要实施会计系统的方式。

所以削减的两种用途都很糟糕。但第二个显然更糟,因为它有更多的前提条件要记住,而且效率低下。 另一方面,在某些情况下您可以使用这些谓词。但通常很难记住何时这是安全的。因此,这种削减是永久性的错误来源。

有没有希望摆脱所有这些细则?幸运的是,使用[a] if_/3 SICStus | SWI的方法可以解决问题。下载并说:

library(reif)

该计划效率相当,但没有任何上述缺陷:

:- use_module(reif).

rm(_,[],[]).
rm(A,[X|Xs], Ys0) :-
   if_(A = X, Ys0 = Ys, Ys0 = [X|Ys]),
   rm(A, Xs, Ys).

注意第二个新答案!它表示对于与?- rm(X, [a], R). X = a, R = [] ; R = [a], dif(X, a). 不同的所有X,列表保持不变。