我参加了一门课程,学习了一些序言.我无法弄清楚如何/何时使用削减.即使我得到了切割的一般概念,我也似乎无法正确使用它们.任何人都可以简单地解释一下,或者给出一个他们可以推荐的"削减"的好教程(那不是learnprolognow.org)吗?
许多系统提供了纯粹而有效的实现member/2.特别是,没有选择点可供选择:
?- member(b,[a,b]).
true.
Run Code Online (Sandbox Code Playgroud)
然而,member/2生产的天真实施相当:
?- member(b,[a,b]).
true ;
false.
Run Code Online (Sandbox Code Playgroud)
从声明的角度来看肯定是正确的,但效率较低.
另一方面,存在一些技术问题member/2.它允许冗余解决方案,如:
?- member(a,[a,a]).
true ;
true.
Run Code Online (Sandbox Code Playgroud)
memberd/2使用if_/3和解决这个问题(=)/3.
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs)).
?- memberd(a,[a,a]).
true.
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个定义使选择点再次打开 - ; false在成员不这样做的情况下产生("剩余的选择点"):
?- memberd(X,[a,b]).
X = a ;
X = b ;
false. % BAD - to be avoided!
?- member(X,[a,b]).
X = a ;
X = b.
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:是否有一个定义memberd/2,避免选择点如上所述?
我有一个如下的条款:
lock_open:-
conditional_combination(X),
equal(X,[8,6,5,3,6,9]),!,
print(X).
这个条款成功了.但是我想知道在之前调用conditional_combination()的次数是多少次equal(X,[8,6,5,3,6,9]).该程序是通过遵循一些规则来生成排列.我需要生成多少个排列来获得像865369这样的特定值.
我有以下简单的表达式解析器:
expr(+(T,E))-->term(T),"+",expr(E).
expr(T)-->term(T).
term(*(F,T))-->factor(F),"*",term(T).
term(F)-->factor(F).
factor(N)-->nat(N).
factor(E)-->"(",expr(E),")".
nat(0)-->"0".
nat(1)-->"1".
nat(2)-->"2".
nat(3)-->"3".
nat(4)-->"4".
nat(5)-->"5".
nat(6)-->"6".
nat(7)-->"7".
nat(8)-->"8".
nat(9)-->"9".
Run Code Online (Sandbox Code Playgroud)
但是,这仅支持1位数字.在这种情况下,如何解析多位数字?
我试图写一个谓词twice(El,L)将返回true.时El是名单正是两次.这是我有的:
twice(El,L) :- select(El,L,L1), member(El,L1), \+ twice(El,L1).
Run Code Online (Sandbox Code Playgroud)
它的效果很好twice(2,[1,2,2,3,4])
但是twice(X,[1,1,2,2,3,3])它为每个数字加倍X = 1 ; X = 1 ; X = 2...我怎么能避免这种情况而不使用任何累加器呢?
神交在序言绿色削减我试图将它们添加到继任算术总和的标准定义(见谓词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..我的问题是:
假设我有以下DCG规则:
factor(X) --> "(", expr(X), ")".
Run Code Online (Sandbox Code Playgroud)
通常这将被翻译为:
factor(X, A, B) :-
[40|C] = A, expr(X, C, D), [41|B] = D.
Run Code Online (Sandbox Code Playgroud)
是否允许Prolog系统将其翻译如下,
即将统一合并到头部和目标中?
factor(X, [40|A], B) :-
expr(X, A, [41|B]).
Run Code Online (Sandbox Code Playgroud)
如果DCG扩展不会坚定,则不允许
将[41 | B]放在expr调用的第三个参数中.
但我想坚定不移,所以一切都应该没问题?
再见
PS:关于坚定性的非正式定义,请参阅:
Richard O'Keefe,2009:
"作为Prolog编程中"坚定"一词的发明者,
我应该赞成它.坚定性基本上
意味着你不能强迫谓词错误
填写输出参数错误的路径."
http://blog.gmane.org/gmane.comp.ai.prolog.swi/month=20090301
PSS:对于其他DCG翻译,请参阅最新的
DCG标准提案.附录包含DCG翻译器
源代码:
ISO/IEC DTR 13211-3:2006
明确条款语法规则
Klaus Daessler
2012年11月20日
N238 DIN草案2012-11-20
P =>程序K =>阻止
S =>单指令
C =>命令
E =>表达
B => Boolean-expr
I =>标识符
N>数字
P :: = K.
K :: =开始C结束
C :: = C1; C2 | 小号
S :: = I:= E | 如果(B)则S | 如果(B)那么S1否则S2 | 而(B)做S | 重复C直到(B)| K | 打印E.
E :: = - E | E1 + E2 | E1 - E2 | E1 E2 | E1 div E2 | E1 mod E2 | (E)| 我| ñ
B :: = E1 = E2 | …
让我们考虑下面的Prolog程序(来自"The Prolog"):
natural_number(0).
natural_number(s(X)) :- natural_number(X).
plus(X, 0, X) :- natural_number(X).
plus(X, s(Y), s(Z)) :- plus(X, Y, Z).
Run Code Online (Sandbox Code Playgroud)
和查询:
?- plus(s(s(s(0))), s(0), Z).
Run Code Online (Sandbox Code Playgroud)
SICStus和SWI都会产生预期的Z = s(s(s(s(0))))答案,但会询问用户下一个答案(正确no/ false答案).但是,我无法理解为什么在找到唯一目标后SLD树中存在一个开放分支.我尝试在SICStus和SWI下调试,但我还不能解释结果.我只能说,据我所知,两者都是回溯plus(s(s(s(0))), 0, _Z2).有人可以帮我理解这种行为吗?
嗨,我正在尝试用这样的语法实现一个简单语言的解析器.
program ::= "program" declarations "begin" statements "end"
declaration ::= "var" ident "as" type
type ::= "string" | "int"
Run Code Online (Sandbox Code Playgroud)
我完成了前两个,我怎么写类型语法?
program( prog( DECLS, STATS ) ) -->
[ 'program' ], declarations( DECLS ),
[ 'begin' ], statements( STATS ), [ 'end' ].
declaration( decl( IDENT, TYPE ) ) -->
[ 'var' ], ident( IDENT ), [ 'as' ], type( TYPE ).
Run Code Online (Sandbox Code Playgroud) prolog ×10
dcg ×3
prolog-cut ×3
clause ×1
count ×1
grammar ×1
iso-prolog ×1
list ×1
parsing ×1
recursion ×1
swi-prolog ×1