CS计算机代考程序代写 prolog database algorithm Declarative Programming

Declarative Programming
Meta-programming in Prolog (2)

Geraint A. Wiggins

Professor of Computational Creativity
Department of Computer Science

Vrije Universiteit Brussel

Summary of previous lecture

I Meta-programming is programming where the data
represents a program

I We say that that data is the name of the program it
represents

I In Prolog, we usually use as a name a term which is
identical to the named program itself

I In Prolog, we usually use a non-ground representation –
i.e., we use variables to name variables

I A better approach is a ground representation – but this
has the disadvantage that we have to handle unification
and variable bindings explicitly

Summary of previous lecture (2)

I It is possible to represent the Prolog execution
mechanism as a meta-program, which refers directly to
the Prolog database

I It is possible to extend and adapt the execution
mechanism in various ways, such as to change the
execution rule, and to admit multiple databases

I Meta-programming can allow significant increases in the
reasoning power of the language, and can allow us to
solve complex problems merely by stating them as logic
programs

Prolog meta-programming facilities

I Meta-programming predicates in Prolog can be divided
into several headings:

I term/instantiation testing
I term manipulation
I database access
I database manipulation
I meta-level identity testing

Instantiation testing

I These predicates are used for testing if the meta-level
representation of a program variable (which is itself a
variable) has a value or not.

var(X) succeeds if X is an uninstantiated variable;
nonvar(X) succeeds if X is not an uninstantiated

variable;
ground(X) succeeds if X is a fully instantiated term.

I For example, a correct use of var/1 might be in an
explicit unification algorithm, where we need to know if
an object is a variable or a term

I They are often abused for preventing object-level calls to
predicates where instantiation is crucial, e.g.,

p( X, Y ) :- ground( Y ),

X is Y.

Syntax checking

I These predicates are used for testing the syntactic shape
of a meta-level term

var(X) succeeds if X is a variable;
atom(X) succeeds if X is a ground atom

float(X) succeeds if X is a ground floating-point
number (real/1 in some implementations)

integer(X) succeeds if X is a ground integer
number(X) succeeds if X is a ground number
atomic(X) succeeds if X is a number or an atom
simple(X) succeeds if X is either a variable or atomic
compound(X) succeeds if X is neither a variable nor

atomic
callable(X) succeeds if X is a well-formed Prolog goal

Prolog term manipulation
I These predicates are very useful for constructing

meta-level terms, but also as short-cuts for building
object-level terms when we really need to

functor(Term,Name,Arity) succeeds when Term has
functor Name and arity Arity

arg(ArgNo,Term,Arg) succeeds when Arg is the
Argnoth argument of Term

Term =.. List (univ) succeeds when List is of the
form [F|L] and F is the functor of Term and
L is a list of its arguments

?- p(a,b) =.. L.

L = [p,a,b]

true

I =../2 is the often the most useful meta-predicate, as it
can remove the need to write infinite numbers of clauses!

Prolog term manipulation (2)

name(Const,CharList) succeeds if Const is an atomic
constant whose name is spelled in CharList

I Notation: we use the term “abc” to denote the string
[97,98,99], which is the list of the ASCII codes for the
letters a, b, c

?- name( ’Geraint’, GList ),

name( ’Wiggins’, WList ),

append( GList, WList, Name ),

name( Whole, Name ).

Whole = ’GeraintWiggins’

true

?- name( ’Geraint’, “Geraint” ).

Prolog database access and manipulation
I Some of these predicates allow us to change the contents

of the Prolog database. If you do this in an arbitrary way,
you will probably damage the logic of your program

clause(Head,Body) succeeds if there is a clause
unifiable with Head :- Body. in the
database. If Head is a fact in the database,
then Body is set to true

assert(Clause) adds Clause to the database
asserta(Clause) adds Clause to the database as the

first clause of the predicate so defined
assertz(Clause) adds Clause to the database as the

last clause of the predicate so defined
retract(Clause) removes the first clause to match

Clause from the database
retractall(Head) removes all the clauses whose head

match Head from the database

Prolog database access/manipulation (2)
I In order to store (parts of) a predicate, the predicate

must be dynamic
I If you build a new predicate, Prolog will make it dynamic

automatically; otherwise you must declare it as dynamic:

:- dynamic p/1.

p(2).

?- assertz( p(1) ),

asserta( p(3) ), listing( p ).

p(3).

p(2).

p(1).

true

The Prolog internal database

I This is covered for historical reasons; there is now false
need to use this facility

I There is a special area of the Prolog database which is
reserved for storing persistent information: the internal
database.

I Each term stored is accessed via a key (for speed) and
assigned a reference number

recorded(Key,Term,Ref) succeeds if the Term is
recorded under Key with reference Ref

recorda(Key,Term,Ref) as for asserta – Ref must
be uninstantiated

recordz(Key,Term,Ref) ditto assertz
erase(Ref) succeeds if a term is stored against

reference Ref and it has been erased

Meta-level identity testing
I There are two predicates for testing syntactic identity at

the meta-level
==/2 succeeds if its arguments are syntactically

identical
\==/2 succeeds if its arguments are not

syntactically identical
I Note the difference between = and ==:

?- X = Y.

X = Y

true

?- X = X.

true

?= f(X) = f(1).

X = 1

true

?- X == Y.

false

?- X == X.

true

?- f(X) == f(1).

false

Meta-level identity testing (2)

I Note also that \== does not mean “not equals”; it means
“syntactically different from” and its result depends on
the instantiation of its variables

I For example,

?- \+ X = X.
false

?- \+ X = Y.
false

?- X \== X.
false

?- X \== Y.
true

I It is incorrect to use \== as object-level “not equals”
because it depends on instantiation

I In the next lecture, we will see how to solve the problems
with the proper object-level “not equals”