'!' 在执行上有什么区别?存在? [英] What is the difference in execution if the cut '!' is present?

查看:209
本文介绍了'!' 在执行上有什么区别?存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

counter([],[]).
counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),!, C1 is C+1.
counter([H|T],[[H,1]|R]) :- counter(T,R).

!"的作用是什么?因为我在上面和下面的代码中都获得了相同的输入输出?

What is the effect of the "!" as I'm getting the same output for an input in both the above and below code?

 counter([],[]).
 counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),C1 is C+1.
 counter([H|T],[[H,1]|R]) :- counter(T,R).

我是 Prolog 的新手.

I'm new to Prolog.

推荐答案

!"的作用是什么?

What is the effect of the "!"

cut 修剪了搜索空间.也就是说,在其他纯粹和单调的程序中,切割将删除一些解决方案或答案.只要这些都是多余的就好了.这听起来很天真和有用,不是吗?一起来看看吧!

The cut prunes the search space. That is, in an otherwise pure and monotonic program, the cut will remove some solutions or answers. As long as those are redundant that's fine. It sounds so innocent and useful, doesn't it? Let's have a look!

免得我忘记了,使用 [E,Nr] 来表示对是相当不寻常的,最好使用对 E-Nr.

And lest I forget, using [E,Nr] to denote pairs is rather unusual, better use a pair E-Nr.

我们现在将比较 counter_cut/2counter_sans/2.

We will now compare counter_cut/2 and counter_sans/2.

| ?- counter_cut([a,a],Xs).
     Xs = [[a,2]].

| ?- counter_sans([a,a],Xs).
     Xs = [[a, 2]]
  ;  Xs = [[a, 1], [a, 1]].     % <<< surprise !!!

所以切割版本的解决方案较少.似乎保留的解决方案 counter_cut/2 是正确的.在这种非常特殊的情况下.它总是会选择正确的吗?我将尝试一个最低限度的更一般的查询:

So the cut-version has fewer solutions. Seems the solution counter_cut/2 retained is the right one. In this very particular case. Will it always take the right one? I will try a minimally more general query:

| ?- counter_cut([a,B],Xs).
     B = a,
     Xs = [[a, 2]].

| ?- counter_sans([a,B],Xs).
     B = a,
     Xs = [[a, 2]]
  ;  Xs = [[a, 1], [B, 1]].

再说一次,_sans 更健谈,这一次,它甚至更正确;最后一个答案包括 B = b.换句话说,

Again, _sans is chattier, and this time, it is even a bit right-er; for the last answer includes B = b. In other words,

| ?- counter_cut([a,B], Xs), B = b.
     fails.              % incomplete !

| ?- counter_sans([a,B], Xs), B = b.
     B = b,
     Xs = [[a,1],[b,1]].

所以有时_cut 版本更好,有时_sans.或者更直接地说:两者都是错误的,但 _sans-version 至少包括所有解决方案.

So sometimes the _cut version is better, and sometimes _sans. Or to put more directly: Both are wrong somehow, but the _sans-version at least includes all solutions.

这是一个净化"版本,它只是将最后一条规则重写为两种不同的情况:一种用于列表的末尾,另一种用于更远的不同元素.

Here is a "purified" version, that simply rewrites the last rule into two different cases: One for the end of the list and the other for a further, different element.

counter_pure([],[]).
counter_pure([H|T],[[H,C1]|R]) :- counter_pure(T,[[H,C]|R]), C1 is C+1.
counter_pure([H],[[H,1]]).
counter_pure([H,D|T],[[H,1]|R]) :- dif(H,D), counter_pure([D|T],R).

从效率的角度来说还不算太出名.

From an efficiency viewpoint that is not too famous.

这里是一个有理树统一系统的效率测试用例:

Here is a test case for efficiency for a system with rational tree unification:

?- Es = [e|Es], counter(Es, Dict).
resource_error(stack).

相反,实现应该平滑循环,至少直到这个宇宙结束.严格来说,该查询必须产生资源错误,但前提是它计数到的数字远大于 10^100000000.

Instead, the implementation should loop smoothly, at least till the end of this universe. Strictly speaking, that query has to produce a resource error, but only after it has counted up to a number much larger than 10^100000000.

这篇关于'!' 在执行上有什么区别?存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆