What's the meaning of Prolog operator '->&

2019-01-29 11:47发布

问题:

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.

回答1:

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:

Goal1 -> Goal2 first executes Goal1 and, in case of success, removes all choice-points created by Goal1 and executes Goal2. This control construct acts like an if-then (Goal1 is the test part and Goal2 the then part). Note that if Goal1 fails ->/2 fails also. ->/2 is often combined with ;/2 to define an if-then-else as follows: Goal1 -> Goal2 ; Goal3. Note that Goal1 -> Goal2 is the first argument of the (;)/2 and Goal3 (the else part) is the second argument. Such an if-then-else control construct first creates a choice-point for the else-part (intuitively associated with ;/2) and then executes Goal1. In case of success, all choice-points created by Goal1 together with the choice-point for the else-part are removed and Goal2 is executed. If Goal1 fails then Goal3 is executed.

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.



回答2:

It is the if/then/else in Prolog, for example

( X mod 2 =:= 0
-> writeln(even)
;  writeln(odd)).


标签: prolog