问题描述
我注意到在一些 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;Goal3
,Goal1 ->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
的结果,Goal2
和 Goal3
的执行是相互排斥的.
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运算符'->'的含义是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!