本文介绍了Prolog运算符'->'的含义是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到在一些 Prolog 程序中使用了运算符 ->,但我不知道它的含义.这是它的使用示例:

swish_add_user(User, Passwd, Fields) :-短语("$1$", E, _), % 使用 Unix MD5 哈希地穴(密码,E),string_codes(Hash, E),条目 = passwd(用户,哈希,字段),绝对文件名(swish(密码),文件,[访问(写入)]),(exists_file(文件)->http_read_passwd_file(文件,数据);数据 = []),( selectchk(passwd(User, _, _), Data, Entry, NewData)->真的;追加(数据,[条目],新数据)),http_write_passwd_file(文件,新数据).

它在这个子句中有什么用?我什么时候应该使用这个运算符,什么时候不应该使用?

PS:代码段取自 authenticate.pl 文件位于 swish 存储库中,这是 Prolog IDE 在线.

解决方案

Joel76 的回答给出了 ->/2 控制结构的最常见用法,该结构定义在ISO 序言.Goal1 -> 的描述GNU Prolog 手册中的目标2是:

目标 1 ->Goal2 首先执行 Goal1,如果成功,移除所有由 Goal1 创建的选择点并执行 Goal2.这个控制结构就像一个 if-then(Goal1 是测试部分,Goal2 是 then 部分).请注意,如果 Goal1 失败 ->/2 也会失败.->/2 经常与 ;/2 结合起来定义一个 if-then-else 如下: 目标 1 ->目标2;目标 3.请注意 Goal1 ->Goal2(;)/2 的第一个参数,Goal3(其他部分)是第二个参数.这种 if-then-else 控制结构首先为 else 部分创建一个选择点(直观地与 ;/2 相关联),然后执行 Goal1.在成功的情况下,由 Goal1 创建的所有选择点连同 else 部分的选择点都将被删除并执行 Goal2.如果 Goal1 失败,则执行 Goal3.

它不像数学逻辑蕴涵(正如它的符号形式可能暗示的那样),因为在这样的蕴涵子句中,F ->T 为真,而在 Prolog 中,如上所述,如果 Goal1 失败,则 ->/2 表达式失败.

在这种情况下,请务必注意运算符的优先级.在Prolog中,优先顺序是,,然后->,然后;.因此,如描述中所述,在 if-then-else 结构中,Goal1 ->目标2;Goal3Goal1 ->Goal2 表达式是 ;/2 的第一个参数.以下是在各种情况下会发生的情况:

目标 1 ->目标2;Goal3 if-then-else 注释----- ----- ----- ------------ -----成功 成功 NE* 成功 Goal1 选择点已移除目标 2 选择点仍然存在(如果存在)成功 失败 NE 失败 Goal1 选择点已删除Fails NE Succeeds Succeeds Goal3 选择点仍然存在(如果存在)失败 网元失败 失败*NE = 未执行

由于优先级的关系,if-then-else 结构通常被加括号,如示例所示:

( selectchk(passwd(User, _, _), Data, Entry, NewData)->真的;追加(数据,[条目],新数据)),胡说八道

如果括号不存在,则 blah-blah 将成为 else 的一部分,如果 selectchk 成功,则不会执行.>

还有一些有趣的事情发生在选择点上.如果 Goal1 成功,Prolog 将调用 Goal2 等,但不会回溯到 Goal1 的更多解决方案(如果存在).举例说明:

a(1).a2).测试 :-(一(X)->写(X),NL;写('没有'),nl).|?- 测试.1是的

在上面,Prolog 没有回去找a(X)X = 2.另一方面,else 可能会发生回溯:

foo :-(  错误的->写('不会发生'),nl;斧头),写(X),NL).|?- 富.1真的 ?;2是的

Goal2 也会发生回溯:

foo :-(   真的->a(X), 写(X), nl;写('其他'),NL).|?- 富.1真的 ?;2是的

但是正如您所看到的,一旦选择了 Goal2 路径,当 Goal3 的解决方案被选择时,就不会回溯到 else (Goal3)code>Goal2 用完了.A 可能是预期的,根据 Goal1 的结果,Goal2Goal3 的执行是相互排斥的.

I have noticed the use of the operator -> in some Prolog programs, but its meaning is unknown to me.This is an example of its use:

swish_add_user(User, Passwd, Fields) :-
    phrase("$1$", E, _), % use Unix MD5 hashes
    crypt(Passwd, E),
    string_codes(Hash, E),
    Entry = passwd(User, Hash, Fields),
    absolute_file_name(swish(passwd), File,
    [access(write)]),
    ( exists_file(File)
    -> http_read_passwd_file(File, Data)
    ; Data = []
    ),
    ( selectchk(passwd(User, _, _), Data, Entry, NewData)
    -> true
    ; append(Data, [Entry], NewData)
    ),
    http_write_passwd_file(File, NewData).

What is its use in this clause? When should I use this operator and when not?

PS: The code segment is taken from the authenticate.pl file in the swish repository, an excellent implementation of a Prolog IDE online, by the way.

解决方案

Joel76's answer gives what is probably by far the most common usage of the ->/2 control construct, which is defined in ISO Prolog. The description given for Goal1 -> Goal2 in the GNU Prolog manual is:

It doesn't act like a mathematical logical implication (as its symbolic form might suggest) because, in such an implication clause, F -> T is true, whereas in Prolog, as mentioned above, if Goal1 fails, then the ->/2 expression fails.

It's important to note operator precedence in this case. In Prolog, the order of precedence is ,, then ->, then ;. Thus, as stated in the description, in an if-then-else construct, Goal1 -> Goal2 ; Goal3, the Goal1 -> Goal2 expression is the first argument of ;/2. Here is what happens in various cases:

Goal1  ->  Goal2  ;  Goal3     if-then-else  Notes
-----      -----     -----     ------------  -----
Succeeds   Succeeds  NE*       Succeeds      Goal1 choice point removed
                                             Goal2 choice point remains (if it exists)
Succeeds   Fails     NE        Fails         Goal1 choice point removed
Fails      NE        Succeeds  Succeeds      Goal3 choice point remains (if it exists)
Fails      NE        Fails     Fails

*NE = not executed

Because of the precedence, the if-then-else constructs are often parenthesized, as in the example:

( selectchk(passwd(User, _, _), Data, Entry, NewData)
-> true
; append(Data, [Entry], NewData)
),
blah-blah

If the parentheses were not there, then blah-blah would become part of the else and not executed if selectchk succeeds.

There is also something interesting that happens to the choice points. If Goal1 succeeds, Prolog will call Goal2, etc, but won't backtrack to more solutions, if they exist, for Goal1. To illustrate:

a(1).
a(2).

test :-
    (  a(X)
    -> write(X), nl
    ;  write('no a'), nl
    ).

| ?- test.
1

yes

In the above, Prolog didn't go back to find X = 2 for a(X). On the other hand, backtracking can occur for the else:

foo :-
    (  false
    -> write('not gonna happen'), nl
    ;  a(X),
       write(X), nl
    ).

| ?- foo.
1

true ? ;
2

yes

Backtracking also occurs for Goal2:

foo :-
    (   true
    ->  a(X), write(X), nl
    ;   write('else'), nl
    ).

| ?- foo.
1

true ? ;
2

yes

But as you can see, once the Goal2 path is chosen, there's no backtracking to the else (Goal3) when solutions for Goal2 are exhausted. A might be expected, executions of Goal2 versus Goal3 are mutually exclusive depending upon the result of Goal1.

这篇关于Prolog运算符'->'的含义是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-16 16:45