SWI Prolog if 语句,它们是如何工作的?生成一个简单的网格 [英] SWI Prolog if statements, how do they work? Generating a simple grid

查看:56
本文介绍了SWI Prolog if 语句,它们是如何工作的?生成一个简单的网格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我意识到我已经从原始代码中删除了 if 语句,这无助于可读性和问题的清晰度.只需跳到答案以了解它们如何与一个小示例程序一起工作.

I realize I've edited out the if statements out of the original code which doesn't help readability and question clarity. Just skip to the answers for the explanation on how they work with a small example program.

为了了解在 Prolog 中使用 if 语句的更复杂的程序,我正在创建一个简单的平台游戏,它生成一些对象并将它们放置在网格中.首先,我试图用在 prolog 中尝试生成事物的想法来生成一个简单的世界".计划是创建一个包含 10000 个项目的 50 个列表的网格,这真的不应该那么复杂,但我无法让 if 语句起作用,因为我觉得我从根本上误解他们的工作方式与我认为他们的工作方式.发生的情况是不满足条件,不调用 if 语句,但使用空变量调用整个谓词,并且不实例化评估.

To learn about more complex programs using if statements in Prolog, I'm creating a simple platformer that generates some objects and places them in a grid. First I'm trying to generate a simple 'world' with the idea of trying out generating things in prolog. The plan is to create a grid of 50 lists with 10000 items, which really shouldn't be that complicated but I can't get the if statements to work as I get the impression that I'm fundamentally misunderstanding how they work vs how I think they work. What happens is the condition isn't met, the if statement isn't called but the whole predicate is recalled with empty variables and evaluations are not instantiated.

  1. 创建一个简单的累加器,它有一个 X 和 Y 轴,并且限制为在使谓词失败之前他们走了多远.
  2. 如果已达到Y行数,则终止
  3. 创建一个新的 [id, point(X,Y), Image] 以备后用
  4. 如果 X = 行尾,X 为 0,否则创建下一个点

代码:

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 条件语句,甚至可以这样使用它们吗?

Am I doing something blatantly wrong or how are you supposed to use prolog conditional statements and can they even be used like this at all?

我希望它的工作方式是评估一个术语,然后执行以下操作左侧的操作,或者如果它为真,或者如果它为假,则执行右侧的操作.会发生这种情况,但我不明白为什么要再次调用整个谓词,因为它还清空了正在评估的变量.我的脑袋疼.

The way I expect it to work is a term is evaluated, then do what is to the left of the following OR if it's true, or the right if it's false. That happens, but I don't understand why the entire predicate is called again as it also empties the variables being evaluated. My brain hurts.

文档内容:http://www.swi-prolog.org/pldoc/man?predicate=-%3E/2

@damianodamiano 发现了问题,prolog 中的 if 语句需要用 () 标签包围.我仍然希望更详细地解释它们在选择点、回溯和其他我可能不知道的 Prolog 特定事物方面的实际工作原理.

@damianodamiano identified the problem, if statements in prolog need to be surrounded by () tags. I'd still like a more detailed explanation of how they actually work in regards to choice points, backtracking and other Prolog specific things I might not even know about.

推荐答案

这是基于我对 ISO-prolog 的理解和给出的其他答案,归结为 if then else 如何的本质在 Prolog 中工作.

This is based on my understanding of ISO-prolog and the other answers given, boiled down to the essence of how if then else works in Prolog.

if 谓词-> 强制评估其周围由() 分组的复杂术语.外括号将 if 语句标识为 ( if -> then ; else ),其中 if,thenelse 是要评估的术语形式的每个目标,返回 yesno,也按 ( 分组).是否调用thenelse,由OR 运算符; 分隔,取决于yesno 结果来自 if 表示的评估项.外部分组是绝对必要的,而内部分组是可选的,但我认为无论如何添加它们是一种很好的做法,因为您可以嵌套另一个 if 语句作为被 () 包围的术语 在第一个的结果中,这可能会产生不需要的结果并使代码更难阅读,并且任何未分组的嵌套 ; 会将右侧标识为 else.

The if predicate -> forces evaluation its the surrounding complex terms grouped by ( and ). The outer brackets identify the if-statement as ( if -> then ; else ), where if,then and else are each goals in the form of terms to be evaluated, which return yes or no, also grouped by ( and ). Whether then or else is called, separated by the OR operator ;, depends on the yes or no result from the evaluated term represented by if. The outer groupings are strictly necessary while the inner ones are optional, BUT it's good practice in my opinion to add them anyway, given that you can nest another if statement as a term surrounded by () in the result of the first, which likely produces unwanted result and makes the code much harder to read, and any non-grouped nested ; will identify the right side as the else.

选择点是在存在变量的地方创建的,这些变量可以有多个可能的答案作为对提出的目标的可能解决方案.这意味着在 if 中,如果一个术语可以通过多种方式满足,Prolog 将尝试将这个目标作为一个单独的目标来满足,然后使用结果来确定周围术语的结果.如果目标失败,它的行为就像普通代码一样,不会尝试更正确地满足目标.

Choice points are created where there are variables that can have multiple possible answers as a possible solution to the posed goal. This means within an if, if a term can be satisfied in multiple ways, Prolog will try to satisfy that goal as a separate goal and then use the result to determine the outcome of the surrounding term. If a goal fails, it behaves like normal code and doesn't try to satisfy the goals further right.

如果选择点在整个 if 语句部分之前,将再次检查整个部分.

If a choice point is before the whole if statement section, the whole section will be checked again.

阐明想法的示例程序.

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)
        ).

的输出是什么?-开始.

first if
first then
second ifsecond ifsecond else

这篇关于SWI Prolog if 语句,它们是如何工作的?生成一个简单的网格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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