酷兔英语

章节正文

Prolog(Programming in Logic的缩写)是一种逻辑编程语言。它建立在逻辑学的理论基础之上, 最初被运用于自然语言等研究领域。

append

The built-in predicate append(?List1, ?List2, ?List1_then_List2) succeeds if List1 followed by List2 = List1_then_List2. Examples:

 

?- append([a, b], [c, d, e], Result).
Result = [a, b, c, d, e].
true.
?- append([a, b], SecondBit, [a, b, c, d, e]).
SecondBit = [c, d, e]
true.
?- append(FirstBit, [c, d, e], [a, b, c, d, e]).
FirstBit = [a, b]
true.

A not uncommon beginner's mistake is to use append([Head], Tail, List) to build a list instead of something like List = [Head | Tail]. This will work, but is like using a bulldozer to dig a hole to plant out a seedling.

Note: there is also an unrelated version of append that takes a single parameter. This is described under files, and is referred to as append/1 - i.e. 1 argument, while the append in this article is referred to as append/3 - 3 arguments.

 

arg

Not a cry of frustration at yet another error message, but rather, an abbreviation for argument, and also the name of a built-in metalogical predicate, that extracts arguments from a structure. Example:

 

?- arg(2, buys(john, beer), Arg).
Arg = beer

It is also possible to put arguments into terms using arg, should this prove useful:

?- X = likes(mary, Y), arg(2, X, pizza).
X = likes(mary, pizza)
Y = pizza

 

argument

See arg, term.

 

 

arithmetic

Many of the usual arithmetic operators are available in Prolog:

OperatorMeaningExample
+addition2 is 1 + 1.
subtraction1 is 2 – 1.
unary minusTry the query X is 1, Y is - X.
*multiplication4 is 2 * 2.
/division2 is 6 / 3.
//integer division1 is 7 // 4.
modinteger remainder3 is 7 mod 4.
**exponentiation1.21 is 1.1 ** 2.

 

Except in the context of an arithmeticcomparison operator, arithmetic expressions need to be explicitly evaluated in Prolog, using the is built-in predicate.

Mostly one uses these operators in a goal more like this:

X is Y + 2

where Y is a variable already bound to a numeric value, or perhaps a arithmeticcomparison goal like this:

X > Y * Z

Here's another example: a rule to tell if a (whole) number is odd:

odd(Num) :- 1 is Num mod 2.

Another way to do this one is to use =:=:

odd(Num) :- Num mod 2 =:= 1.

If you wanted to be more cautious, you could first check that Num is in fact a whole number:

odd(Num) :- integer(Num), 1 is Num mod 2.

 

As usual in digital computations, with fractional numbers, it is necessary to be careful with approximation issues. Thus the final example in the table above, 1.21 is 1.1 ** 2.actually fails when typed into Prolog as a query. This is because 1.1 ** 2, as represented in computers, actually comes out to be something like 1.210000000001. See the section on comparison operators for a solution to this issue.

Note that SWI Prolog does some apparently strange stuff in the domain of arithmetic (dialogue below done with SWI-Prolog Version 5.6.58):

?- X is [a].
X = 97.
?- X is [a] + [b].
X = 195.
?- X is sqrt(23456).
X = 153.154.
?- X is sqrt([23456]).
X = 153.154.
?- X is sqrt(123456789).
X = 11111.1.
?- X is sqrt([123456789]).
X = 13.3791.

The ASCII code for a is 97, which sort of explains the first two query outcomes. The last pair of queries are particularly strange. It is best to avoid relying on this sort of thing, and stick to standard arithmetical notation. Avoid strange tricks: code should be comprehensible.

 

See also comparison operators, built-in functions.

 

arity

The arity of a functor is the number of arguments it takes. For example, the arity of likes, as in likes(jane, pizza), is 2, as it takes two arguments, jane and pizza.

ArityExampleCould Mean ...
0linux.a bit like #define LINUX in* C
1happy(fido).Fido is happy.
2likes(jane, pizza). 
3gave(mary, john, book).Mary gave John a book.

* hard to use in practice in Prolog: if the code contains linux. then you could test for this, but if it doesn't, then testing linux in your code will trigger an "Undefined procedure: linux/0" error. You can work around this by declaring linux to be dynamic - i.e. putting the line

:- dynamic linux/0.

in your code (usually at the start).

 

Every fact and rule in a Prolog program, and every built-in predicate has an arity. Often this is referred to in descriptions of these facts and rules, by appending / and the arity to the name of the rule or fact. For example, the built-in predicate member/2 has arity 2.

A fact or rule can have more than one arity. For example, you might want to have two versions of make terms:

% make(X, Y, Z): X makes Y for Z
make(fred, chest_of_drawers, paul).
make(ken, folding_bicycle, graham).
% make(X, Y): X makes Y
make(steve, fortune).
make(kevin, mistake).

What we have here are make/3 and make/2.

 

 

assert, asserta, assertz

assert is a meta-predicate that adds its single argument, which may be a fact or a rule, to the Prolog database. The idea is that you construct or learn a new fact or rule in the course of executing your Prolog program, and you want to add it to the database. asserta ensures that the added fact/rule is added before any other facts or rules with the same functor), while assertz adds the fact after any other rules or facts with the same functor. When more than one rule/fact with the same functor is present in the database, they are tried in the order that they appear in the database, hence the need for asserta and assertz. You would use asserta in the common case where the new fact is supposed to save the effort involved in checking the fact using rules and other facts. You might use assertz, for example, if you were trying to construct a queue data structure (where items are added to the end of the queue. Examples:

 

?- assert(rich(mary)).
true.
?- rich(mary).
true.
?- assert((happy(X) :- rich(X), healthy(X))).
X = _G180
?- assert(healthy(mary)).
true.
?- happy(X).
X = mary

Facts/rules that are loaded from a file cannot be mixed with facts/rules that are created using assert/asserta/assertz without take the special step of declaring the procedure in question to be dynamic. For example, if you have a rule to say, computeN!, with header factorial(+N, -Result), i.e with functor factorial and arity 2, and you also want to use asserta to add pre-computed values of some factorials to the Prolog database (see also memoisation), then you need to declare factorial to be dynamic, by including the following with your loaded rules for factorial:

:- dynamic factorial/2.

Programs with asserted facts and rules can be extra hard to debug.

See also retract, retractall, dynamic.

 

atom

An atom, in Prolog, means a single data item. It may be of one of four types:

  • a string atom, like 'This is a string' or
  • a symbol, like likes, john, and pizza, in likes(john, pizza). Atoms of this type must start with a lower case letter. They can include digits (after the initial lower-case letter) and the underscore character (_).
  • the empty list []. This is a strange one: other lists are not atoms. If you think of an atom as something that is not divisible into parts (the original meaning of the word atom, though subverted by subatomic physics) then [] being an atom is less surprsing, since it is certainly not divisible into parts.
  • strings of special characters, like <--->, ..., ===>. When using atoms of this type, some care is needed to avoid using strings of special characters with a predefined meaning, like the neck symbol:-, the cut symbol!, and various arithmetic and comparison operators.
    The available special characters for constructing this class of atom are: +, -, *, /, <, >, =, :, ., &, _, and ~.

 

Numbers, in Prolog, are not considered to be atoms.

atom is also the name of a built-in predicate that tests whether its single argument is an atom.

?- atom(pizza).
true.
?- atom(likes(mary, pizza)).
false.
?- atom(<-->).
true.
?- atom(235).
false.
?- X = some_atom, atom(X).
X = some_atom.

The final example means that atom(X) has succeeded, with X bound to some_atom.

 

atom_chars

The built-in Prolog predicate atom_chars can convert an atom into the list of its constituent letters, or vice-versa. A fairly broad concept of atom is used: this predicate will glue together (or split up) any reasonable characters you give it. A possible list would be to put together a list of letters read, one character at a time, to make a word - that is, an atom whose name is the word. Examples:

 

?- atom_chars(pizza, List).
List = [p, i, z, z, a]
?- atom_chars(Atom, [b, e, e, r]).
Atom = beer
?- atom_chars(2007, List).
List = ['2', '0', '0', '7']
?- atom_chars(Atom, ['[', '3', ' ', ',', '4', ']']).
Atom = '[3 ,4]' 

See also atom_codes.

 

atom_codes

The built-in Prolog predicate atom_codes can convert an atom into the list of the numeric codes used internally to represent the characters in the atom, or vice-versa. Examples:

 

?- atom_codes(pizza, List).
List = [112, 105, 122, 122, 97] 
?- atom_codes(Atom, [98, 101, 101, 114]). 
Atom = beer 

See also atom_chars



文章标签:词典  

章节正文