我在掌握Prolog的书中有以下Prolog,我正在尝试学习一些简单的递归。
Json
我不完全确定为什么它不起作用,我已经花了好几个小时摆弄它。任何帮助甚至指向我正确的方向非常感谢。提前谢谢。
答案 0 :(得分:2)
您在此示例中遇到的主要困难是低级算术谓词的所谓 modedness 。例如,让我们使用您发布的代码尝试最常规查询:
?- mins_to_hours(In, H, M). ERROR: Arguments are not sufficiently instantiated
为了摆脱这个缺点,我首先用CLP(FD)约束替换低级谓词,这些谓词在所有主要的Prolog系统中都可用,并简化了对代码的推理。
为此,我只需将(<)/2
替换为(#<)/2
,将(is)/2
替换为(#=)/2
等。(根据您的Prolog系统,您可能还需要导入库为此):
mins_to_hours(In, H, M):- In #< 60, H = 0, M #= In. mins_to_hours(In, H, M):- In #>= 60, In1 #= In-60, H1 #= H+1, mins_to_hours(In1, H1, M).
现在,让我们再次尝试最常见的查询,其中所有参数都是新变量:
?- mins_to_hours(In, H, M). In = M, H = 0, M in inf..59 ; H = -1, In in 60..119, M+60#=In, M in 0..59 ; H = -2, In in 120..179, _5238+60#=In, _5238 in 60..119, M+60#=_5238, M in 0..59 .
在这里,H
可以假设负值似乎很奇怪!
让我们尝试一些具体的案例:
?- mins_to_hours(30, H, M). H = 0, M = 30 ; false.
这似乎还算不错!
?- mins_to_hours(60, H, M). H = -1, M = 0 ; false.
这似乎已经少确定了!
通过一些练习,很容易看出原因:在第二个条款中,您无意中混淆了H
和H1
的角色!假设我们写这样的第二个句子:
mins_to_hours(In, H, M):- In #>= 60, In1 #= In-60, H #= H1+1, mins_to_hours(In1, H1, M).
然后我们得到:
?- mins_to_hours(60, H, M). H = 1, M = 0 ; false.
还有两个案例:
?- mins_to_hours(500, H, M). H = 8, M = 20 ; false. ?- mins_to_hours(1000, H, M). H = 16, M = 40 ; false.
看起来很不错!
请注意,如果您坚持使用较低级别的算术,则无法轻松纠正错误:使用(<)/2
和(is)/2
等谓词要求您还要考虑实际的执行顺序的Prolog,这对几乎所有初学者来说都太难了。我强烈建议您使用CLP(FD)约束,因为它们可以让您轻松尝试不同目标顺序的效果,同时保持关系正确并且一般。