我参加了一门课程,学习了一些序言.我无法弄清楚如何/何时使用削减.即使我得到了切割的一般概念,我也似乎无法正确使用它们.任何人都可以简单地解释一下,或者给出一个他们可以推荐的"削减"的好教程(那不是learnprolognow.org)吗?
我正在解析一个由一系列行组成的相当简单的文件格式,每行都有一些空格分隔的字段,如下所示:
l 0x9823 1
s 0x1111 3
l 0x1111 12
?
Run Code Online (Sandbox Code Playgroud)
我正在使用SWI-Prolog.这是我到目前为止的DCG:
:- consult(library(pure_input)).
load_trace(Filename, Traces) :-
phrase_from_file(trace_file_phrase(Traces), Filename).
trace_file_phrase([]) --> [].
trace_file_phrase([T|Ts]) --> trace_phrase(T), trace_file_phrase(Ts).
trace_phrase(access(Type, Address, SinceLast)) -->
access_type(Type), space,
address(Address), space,
nat(SinceLast), newline.
access_type(load) --> "l".
access_type(store) --> "s".
address(Number) --> "0x", hexnum(Number).
hexdigit(N) --> digit(N).
hexdigit(10) --> "a". hexdigit(11) --> "b". hexdigit(12) --> "c".
hexdigit(13) --> "d". hexdigit(14) --> "e". hexdigit(15) --> "f".
hexnum(N) --> hexdigit(D), hexnum(D, N).
hexnum(N, N) --> [].
hexnum(A, N) --> hexdigit(D), …Run Code Online (Sandbox Code Playgroud) 我试图通过阅读Ulle Endriss的讲义来了解Prolog编程.当我对练习的解决方案没有达到预期的效果时,我发现很难给出一个很好的解释.我认为这与我对Prolog评估表达式的方式的不稳定理解有关.
第20页的练习2.6调用谓词的递归实现,该谓词的last1行为类似于内置谓词last.我的尝试如下:
Run Code Online (Sandbox Code Playgroud)last1([_ | Rest], Last) :- last1(Rest, Last). last1([Last], Last).
它给出了正确的答案,但对于具有多个元素的列表,我必须键入分号才能终止查询.这last1与内置的不同last.
?- last1([1], Last).
Last = 1.
?- last1([1, 2], Last).
Last = 2 ;
false.
Run Code Online (Sandbox Code Playgroud)
如果我切换我声明规则和事实的顺序,那么我需要在两种情况下键入分号.
我想我知道为什么Prolog认为last1可能还有一个解决方案(因此是分号).我想它遵循评估顺序
last1([1, 2], Last).
==> last1([2], Last).
==> last1([], Last). OR Last = 2.
==> false OR Last = 2.
Run Code Online (Sandbox Code Playgroud)
这似乎表明我应该寻找一种方法来避免匹配Rest带[].无论如何,我没有解释为什么切换声明的顺序应该有任何影响.
问题1: 对行为的正确解释是last1什么?
问题2: 如何实现last1与内置无法区分的谓词last?
当我们使用带有cut运算符的append时会出现什么问题?
append2([],L,L):-!.
append2([H|T],L,[H|TL]):-append2(T,L,TL).
Run Code Online (Sandbox Code Playgroud)
我尝试了几种不同的输入,但它总是成功的.
?- append2([1,2],[5],L).
L = [1, 2, 5].
?- append2([1,2],[1,2],L).
L = [1, 2, 1, 2].
?- append2([],[1,2],L).
L = [1, 2].
?- append2([1,2],[],L).
L = [1, 2].
Run Code Online (Sandbox Code Playgroud) 神交在序言绿色削减我试图将它们添加到继任算术总和的标准定义(见谓词plus中什么是该查询的SLD树?).这个想法是通过消除所有无用的回溯(即,没有... ; false)尽可能"清理"输出,同时在参数实例化的所有可能组合下保持相同的行为 - 所有实例化,一个/两个/三个完全未实例化,以及所有变化包括部分实例化的args.
这是我在尝试尽可能接近这个理想时能够做到的事情(我承认错误的答案是如何插入绿色切割append/3作为来源):
natural_number(0).
natural_number(s(X)) :- natural_number(X).
plus(X, Y, X) :- (Y == 0 -> ! ; Y = 0), (X == 0 -> ! ; true), natural_number(X).
plus(X, s(Y), s(Z)) :- plus(X, Y, Z).
Run Code Online (Sandbox Code Playgroud)
在SWI下,这似乎适用于所有查询但有形状的查询?- plus(+X, -Y, +Z).,如SWI的谓词描述符号.例如,?- plus(s(s(0)), Y, s(s(s(0)))).收益率Y = s(0) ; false..我的问题是: