11.4 Returning values from rules (Ad)

The problem

Consider the following query:

?- same_semester(name(Martin), name(John)).

As we saw earlier, the answer is:

{}

This is not very helpful if we wanted to know what semester they were in.

The problem can be formulated in the following general terms: How do we "return" a value from a call to a rule? While executing the body of the rule, we know what semester they are in; it is stored in the variable "S":

same_semester(A,B) :- student(A,S), student(B,S).

"S" is a variable which we use as an intermediate place-holder while executing the body of the rule. How do we return the information contained in S so that it is available even after the body of the rule has been executed?

The solution

The solution is to modify the head of the rule so that it contains a variable which we can use to return the result. In this case, we might as well use the variable which we are using the body of the rule:

same_semester(A,B,S) :- student(A,S), 
                        student(B,S).

The full program so far

The full example program so far looks like this:

student(name(Lisa), semester(5)).
student(name(Martin), semester(3)).
student(name(John), semester(3)).
student(name(Edward), semester(7)).

same_semester(A,B) :- student(A,S), 
                      student(B,S).

same_semester(A,B,S) :- student(A,S), 
                        student(B,S).

It is available in the AAU sample directory as "Students4.plgCG".

Testing the new rule

Let us ask a query:

?- same_semester(name(John), name(Martin), S).

The answer is:

{S = semester(3)}

We have used the variable S to get feedback from the rule. We could equally well have asked:

?- same_semester(name(John), name(Martin), semester(3)).

and the answer would be:

{}

("yes") as we would expect.

The two rules coexist peacefully

Note that the two rules coexist peacefully side by side. They are not in conflict with each other. Why is this?

Recall that two structures match only if:

  1. Their functors are the same
  2. Their arities are the same
  3. Their individual arguments match from left to right.

Here, the functors are the same, so requirement 1. is fulfilled, but their arities are not the same, so requirement 2. is not fulfilled. The first rule has arity 2, while the second rule has arity 3.

Why is it important that the two structures do not match? It is important because, when answering queries (and when executing bodies of rules), matching is the process that drives the sequence of events. For example, the following query:

?- same_semester(name(Lisa), Y).

would not invoke our new rule, since the query uses the structure with arity 2. The new rule has arity 3, and so the subgoal in the query does not match the new rule. Therefore, the new rule is not used to answer the query.

A deeper look at returning values

So the technique for returning values from a rule is to include a variable in the head of the rule which can be used for returning the desired value.

However, there is nothing special about adding an extra variable to the arguments of the head of a rule. As we saw, we can ask questions like:

?- same_semester(name(Martin), name(John), S).

as well as questions like:

?- same_semester(name(Martin), name(John), semester(3)).

The only difference between the two queries is the usage of a variable versus the usage of a value (in this case, a structure) as one of the arguments to the rule.

This is one reason why Prolog is so useful: You can freely decide when to use variables and when to use values as the arguments to rules and facts (collectively called 'clauses', remember?). Prolog will either find the value (if you have used a variable), or use the value (if you supply a value).

Thus there is really nothing new in this technique. There is no fundamental difference between the way the following two questions are answered:

?- student(name(Lisa), S).
?- student(name(Lisa), semester(3)).

and the way following two questions are answered:

?- same_semester(name(Martin), name(John), S).
?- same_semester(name(Martin), name(John), semester(3)).

In both cases, we either use a variable or a value as the input to a rule-invocation. And in both cases, Prolog either finds a value for the variable or uses the value supplied.

Summary

When wanting to return a value from a rule, the technique is to include an extra variable in the arguments to the rule. This variable is then given the desired value in the body of the rule.

There is nothing fundamentally different between:

  • including an extra variable in the arguments and
  • using variables which will normally be used as input.

When asking questions, the user is free to use either variables or values as arguments to the rule invoked.

Next

Next, we have a quiz.


Prev: 11.3 Variable scoping rule
Up: 11 Rules
Next: 11.5 Quiz: Rules