酷兔英语

章节正文

unification, =, =
When we write a goal like X = Y in Prolog, we are testing for more than simple equality in the mathematical sense. We are testing whether X (which might be a variable, an atom, or an arbitrarily complex term) unifies with Y (which might also be an atom, a variable, or a term). Two atoms, including numeric atoms, unify if they are the same. Two more complex terms unify if they have the same functor and their corresponding arguments unify. A variable always unifies with a term (provided that it is not previously unified with something different) by binding to that term. Examples:
?- fred = fred.
true.
  
fred unifies with fred - they are the same atom.
?- X = fred.
X = fred
  
X unifies with fred by bindingX to fred.
?- X = likes(mary, pizza).
X = likes(mary, pizza).
  
X unifies with likes(mary, pizza) by bindingX to likes(mary, pizza).
?- likes(
|        mary,
|        book(
|             title(Title),
|             author(
|                    given('Herman'),
|                    SurnameTerm)))
|  =
|  likes(
|        Who,
|        book(
|             title('Moby Dick'),
|             author(
|                    given('Herman'),
|                    surname('Melville')))).
Title = 'Moby Dick',
SurnameTerm = surname('Melville'),
Who = mary.
  
Note that the | characters at the start of each line are continuation prompts from Prolog because this query has been spread over more than one line.
Title, SurnameTerm, and Who are bound in order to achieve unification. The primary functors of the terms on either side of the = match, and unification proceeds by matching pairs of corresponding arguments, for example, by matching and unifying the first argument on the left, mary, with the first argument on the right, Who. Unification succeeds if all of the arguments match. This will include recursively matching the arguments of substructures such as the author/2 substructures.

 

The goal X = Y succeeds if X = Y would fail; it is the negated form of =.

Unnecessary Use of "=" to Force Unification

This is basically a style issue. Consider the two following alternative pieces of Prolog code for computing the maximum of two numbers.

max1(X, Y, X) :- X > Y.
max1(X, Y, Y) :- X =< Y.
versus
max2(X, Y, Max) :- X > Y, Max = X.
max2(X, Y, Max) :- X =< Y, Max = Y.

The first version is to be preferred, particularly for a novice Prolog programmer, because it reinforces how Prolog works. It also does not involve the unnecessary Max = X or Max = Y.

Whenever you write "=" in a Prolog procedure, review the code to see whether you can get rid of the "=" clause by replacing the item on the left of "=" by the item to the right of it, elsewhere in the procedure. If you do this with max2, you get max1. Sometimes you may have written the "=" with the variable on the right, in which case you need to instead replace the item on the right of the "=" with the item to the left of it.

It should be possible to do this whenever there is a variable (rather than a more complex term) on at least one side of the "=".

univ, =..
The =.. meta-predicate, pronounced "univ", can be used to convert a list whose first item is a non-numeric atom, into a term, and vice-versa. For example,
?- Term =.. [likes, mary, pizza].
Term = likes(mary, pizza).
or
?- likes(mary, pizza) =.. List.
List = [likes, mary, pizza].

Here are some other examples:

?- Term =.. [this, predicate, works, with, longer, lists, too].
Term = this(predicate, works, with, longer, lists, too).
?- Term =.. [one].
Term = one.
?- Term =.. [one, two].
Term = one(two).

 

univ works with infix operators, too, though perhaps in a slightlyunexpected way. Two examples:

?- op(700, xfy, and).
true.
?- Term =.. [and, p, q].
Term = p and q
?- Expression =.. [+, 2, 3], Value is Expression.
Expression = 2+3
Value = 5

 

 

variable
A variable in Prolog is a string of letters, digits, and underscores (_) beginning either with a capital letter or with an underscore. Examples:
X, Sister, _, _thing, _y47, First_name, Z2
The variable_ is used as a "don't-care" variable, when we don't mind what value the variable has. For example:
is_a_parent(X) :- father_of(X, _).
is_a_parent(X) :- mother_of(X, _).

That is, X is a parent if they are a father or a mother, but we don't need to know who they are the father or mother of, to establish that they are a parent.

 

Variables are used in more than one way:

  • to express constraints in parts of a rule:
    likes(A,B) :- dog(B), feeds(A,B).
    Note that both A and B appear on both sides of the neck symbol - the appearance of the same variable in two (or more places) in effect says that when the variable is bound to a value, it must be bound to the same value in all the places that it appears in a given rule.
    Note that if the same variable appears in two or more different rules, it might be bound to different values in the different rules. This is achieved by Prolog renaming the variables internally, when it comes to use the rule - usually the names are things like _1, _2, _3, etc. This is why variables with names like these sometimes turn up in error messages when your Prolog program goes wrong.

     

  • to formulate queries, as in the following example:
    ?- studies(X, 9311). Prolog responds by finding all the values for X for which studies(X, 9311) is true, and successively listing them, e.g.
    X = fred ;X = jane ;X = abdul ;X = maria ;

 

 

 

white space
In writing code in Prolog or any other programming language, white space (blank lines, indentation, perhaps alignment of related data items) can be used to make the code easier to follow. Here are some suggestions:

 

  • Put a blank line before the start of any prolog procedure.
  • Group collections of facts using blank lines.
  • Sometimes it helps to line up comments, but not at the expense of making lines longer than about 75-80 characters.
  • Don't put helper procedures in the middle of other procedures: separate them out before or after the procedure they help. If your helperprocedure is used in several other procedures, you might want to put it right at the end of all your code.

 

Example. In moderate size browser windows, the bad example will have long lines that are folded by the browser, and the good example will not. In practice, you could make the lines in the good example rather longer - up to 75-80 characters.

GoodBad
% smallest(+ListOfNumbers, -Min)
%  binds Min to the smallest item
%  in the non-empty ListOfNumbers.
%  ListOfNumbers should be instantiated
%  at time of call.
smallest([FirstNum], FirstNum).
smallest([FirstNum | Rest], Min) :-
      smallest(Rest, MinRest),
      smaller(FirstNum, MinRest, Min).
 
% smaller(+First, +Second, -Smaller)
%  helper procedure for smallest.
smaller(A, B, A) :-
      A <= B.
smaller(A, B, B) :-
      B < A.
% smallest(ListOfNumbers, Min) binds Min to the smallest item in the non-empty ListOfNumbers. ListOfNumbers should be instantiated at time of call.
smaller(A, B, A) :- A <= B.
smaller(A, B, B) :- B < A.
% This is a helperprocedure for smallest.
smallest([FirstNum], FirstNum).
smallest([FirstNum | Rest], Min) :- smallest(Rest, MinRest), smaller(FirstNum, MinRest, Min).

 

See also indentation and comments. 



文章标签:词典  

章节正文