SWI Prolog if语句,它们是如何工作的? 生成一个简单的网格
我意识到我已经编辑出了原始代码中的if
语句,这不利于可读性和问题的清晰度。 只是跳到答案,解释他们如何使用一个小例子程序。
要了解更多在Prolog中使用if
语句的复杂程序,我将创建一个简单的平台生成器,生成一些对象并将它们放置在网格中。 首先,我试图通过在序言中尝试生成事物的想法来生成一个简单的“世界”。 计划是创建一个包含10000个项目的50个列表的网格,但实际上不应该那么复杂,但我不能让if
语句正常工作,因为我的印象是,我从根本上误解了它们的工作原理,认为他们工作。 会发生什么情况是没有满足条件,if语句没有被调用,但整个谓词被调用空变量和评估没有实例化。
码:
generate(WorldList) :- generate_world(WorldList,0,_,10000,0,_,50).
generate_world([H|T],X,_,XEnd,Y,_,YEnd) :-
%Y has been filled with 50 rows, end recursion
not(Y > YEnd),
%iterate X by 1, store in XNew
XNew is X + 1,
%create a new [id,point(X,Y), Image]
H = [XNew,point(_,_)],
%if X has reached 10k, add 1 to Y and create a new row
X = XEnd -> YNew is Y + 1,
generate_world(T,0,_,XEnd,YNew,_,YEnd);
%continue adding items to current row Y
generate_world(T,XNew,_,XEnd,Y,_,YEnd).
generate_world([],_,_,_,_,_,_).
我在做一些明显错误的事情,或者你应该如何使用prolog条件语句,甚至可以像这样使用它们?
我期望它的工作方式是评估一个术语,然后在下面的左边或者如果它是真的,或者如果它是错误的右边。 发生这种情况,但我不明白为什么整个谓词再次被调用,因为它也清空了被评估的变量。 我的脑袋疼。
文档的内容如下:http://www.swi-prolog.org/pldoc/man?predicate=-%3E/2
@damianodamiano发现了这个问题, if
prolog中的语句需要被()
标签包围。 我仍然想要更详细地解释他们在选择点,回溯和其他我可能不知道的Prolog特定事物方面的实际工作方式。
你的谓词一旦停止运行就会停止,因为在not(By > YEnd)
, By
没有实例化(注意By
也是一个单例变量,每个单例变量都是无用的,并且可能导致错误)。 在这里,我发布了两个实现,第一个没有if语句(个人喜欢),第二个语句(我已经把2
和2
作为简洁的界限......)。
首次实施:
generateList(L):-
generateWL(L,0,2,0,2).
generateWL([],0,_,Y,Y). %you can add a ! here
generateWL(L,MaxX,MaxX,R,MaxR):- %you can add a ! here
R1 is R+1,
generateWL(L,0,MaxX,R1,MaxR).
generateWL([H|T],X,MaxX,R,MaxR):-
X < MaxX,
R < MaxR,
X1 is X+1,
H = [X1,point(X1,R)],
generateWL(T,X1,MaxX,R,MaxR).
?- generateList(WL).
WL = [[1, point(1, 0)], [2, point(2, 0)], [1, point(1, 1)], [2, point(2, 1)]]
false
如果你想防止回溯,只需添加我已注释的两个剪辑。
第二次实施
generateList2(L):-
generateWLIf(L,0,2,0,2).
generateWLIf([H|T],X,MaxX,R,MaxR):-
( X < MaxX, R < MaxR ->
X1 is X+1,
H = [X1,point(X1,R)],
generateWL(T,X1,MaxX,R,MaxR)
; X = MaxX, R < MaxR ->
R1 is R+1,
generateWL([H|T],0,MaxX,R1,MaxR)
; R = MaxR -> T = []).
?- generateList2(WL).
WL = [[1, point(1, 0)], [2, point(2, 0)], [1, point(1, 1)], [2, point(2, 1)]]
(继续评论)
我期望的[条件语句]的工作方式是评估一个术语,然后在下面的左边或者如果它是真的,或者如果它是错误的,则执行右边的操作。 发生这种情况,但我不明白为什么整个谓词再次被调用,因为它也清空了被评估的变量。
你可能意味着它回溯,原因是比较not(Y > YEnd)
最终失败,并且没有其他任何子句(如果两者都没有)。
此外,您的基本情况是没有意义的,因为列表输出不是输入。 而你想与XNew
比较而不是X
generate(WorldList) :-
generate_world(WorldList,1,10000,1,50).
generate_world(T,X,XEnd,Y,YEnd) :-
( Y = YEnd ->
T = []
; T = [point(X,Y)|Rest], XNew is X + 1,
( XNew = XEnd -> YNew is Y + 1,
generate_world(Rest,1,XEnd,YNew,YEnd)
; generate_world(Rest,XNew,XEnd,Y,YEnd) ) ).
这看起来很有效,因为它可以完成你所描述的内容,但这不是很好的设计。 现在你必须一直通过这个庞大的列表,更新一个位置意味着解构列表。
你的问题:
我创建了一个简单的平台生成器,生成一些对象并将它们放置在网格中。 首先,我试图通过在序言中尝试生成事物的想法来生成一个简单的“世界”。 计划是创建一个包含10000个项目的50个列表的网格
在Prolog中通过具有谓词location/3
(例如,参数是坐标和内容)解决得更好。
location(1,1,something).
location(1,2,something).
location(1,3,somethingelse).
...
这个谓词是动态创建的,使用assert/3
。
这是基于我对ISO-prolog和其他答案的理解,归结为if then else
在Prolog中起作用的本质。
if
谓词->
强制评估其周围由(
和)
分组的复杂术语。 外括号将if语句标识为( if -> then ; else )
,其中if
, then
和else
是每个要评估的术语形式的目标,它们返回yes
或no
,也按(
和)
分组。 无论then
或else
被调用,通过OR运算符分开;
取决于由if
表示的评估术语的yes
或no
结果。 外部分组是非常必要的,而内部分组是非必要的,但鉴于您可以嵌套另一个if
语句作为第一个结果中的()
包围的术语,所以我认为最好添加它们,这可能会产生不想要的结果,并使代码更难以阅读,以及任何非分组嵌套;
将确定右侧为else
。
选择点是在有变量的情况下创建的,这些变量可以有多个可能的答案作为可能的解决方案。 这意味着内的if
,如果一个术语可以以多种方式来满足,Prolog的会尽量满足这一目标作为一个单独的目标,然后用结果来确定周围长期的结果。 如果一个目标失败了,它的行为就像普通的代码,并且不会进一步满足目标。
如果选择点位于整个if
语句部分之前,则将再次检查整个部分。
示例程序来澄清这个想法。
fact(a).
fact(f).
start :-
(
%The entire complex term is evaluated as yes
(fact(a), write('first if'), nl) ->
%triggers the first line
(write('first then'),nl) ;
(write('first else'),nl)
),
(
%The entire complex term is evaluated as no
(fact(B), write('second if'), B = b, nl) ->
(write('second then'),nl) ;
%triggers the second line
(write('second else'),nl)
).
并输出?- start.
first if
first then
second ifsecond ifsecond else
链接地址: http://www.djcxy.com/p/66949.html
上一篇: SWI Prolog if statements, how do they work? Generating a simple grid