This section includes predicates for identifying, comparing and manipulating terms. The general categories are:
There are a handful of fundamental types of terms in Prolog. The predicates described in this section can be used to test the type of a given term. There are subtypes among the number type, which can also be tested for, and are described in the section on number types.
term_type/2 takes an input TERM, and returns an atom describing the type. TYPE will be one of:
atom, string, list, structure, number, or var.
atomic/1 succeeds if X is currently instantiated to an atomic primitive type, such as an atom or string or number. It is the opposite of compound/1. If X is a structure or list, atomic/1 fails.
atom/1 succeeds if X is currently instantiated to an atom; else it fails.
string/1 succeeds if X is currently instantiated to a string; else it fails.
number/1 succeeds if X is currently instantiated to a numeric type, such as integer, float or real. The different types of number can also be tested for, as described in the section on number types.
compound/1 succeeds if X is currently instantiated to either a structure or a list. It fails if X is an atomic primitive. It is the opposite of atomic/1.
structure/1 succeeds if X is currently instantiated to a structure; else it fails.
list/1 succeeds if X is currently instantiated to a list; else it fails. Note that '', which is called the empty list, is really an atom. So list() fails as well, and conversely, atom() succeeds. See is_list/1 below.
is_list/1 succeeds if X is instantiated to a list OR the empty list, '', which is really an atom.
var/1 succeeds if X is an unbound variable; else it fails.
nonvar/1 succeeds if X is not an unbound variable; else it fails.
Equality or non-equality of terms can be determined in a variety of ways. The key difference is whether or not variable unification is to take place.
The '=' operator unifies the variables in the terms to be compared.
The '==' operator does not unify the variables, so a variable will NOT be equal to anything other than the same unbound variable.
not(not()) is a common Prolog trick that tests if a goal would be made true by unification, but does not do the unification.
See copy_term/2 as another way to avoid unification of variables in terms.
?- a = X. X = a yes ?- X = Y. X = H3 Y = H3 yes ?- a == a. yes ?- a == X. no ?- X == Y. no ?- X == X. X = H3 yes ?- not(not(a = X)). X = H4 yes ?- not(not(X = Y)). X = H3 Y = H4 yes
X = Y succeeds if X can be unified with Y. See discussion and examples above.
X \= Y succeeds if X cannot be unified with Y.
X == Y succeeds if X and Y are identical, i.e., they unify with no variable bindings occurring. See discussion and examples above..
X \== Y succeeds if X and Y are not identical.
not(not(X = Y)) Succeeds if X can be unified with Y, but doesn't do the unification. See discussion and examples above.
Two terms may be compared via the standard ordering, which is variables @< numbers @< atoms @< strings @< structures @< lists.
Variables can either be sorted as equal or arbitrarily compared based on their internal memory locations. The decision is made based on the value of the Prolog flag vars_sort_equal. If the value is on, then they sort as equals, if it is off they sort based on internal order. The default is off.
So two variables at the same location sort as equal.
Numbers compare in the obvious way, which is contrary to the ISO standard which asks that floating point numbers sort before integers.
Atoms and strings compare alphabetically by ASCII (Unicode) order.
Structures compare alphabetically by functor first, arity second and then by the comparison of each argument.
Lists compare by length first, then by each element.
Two terms may be compared via the standard ordering using these operators.
X @< Y succeeds if X is less than Y in the standard order
X @> Y succeeds if X is greater than Y in the standard order
X @=< Y succeeds if X is less or equal to Y in the standard order
X @> '=' Y succeeds if X is greater or equal to Y in the standard order
compare compares terms Term1 and Term2 using the standard ordering. Unifies Result with ==, <, or > depending on the sort order of Term1 and Term2.
These predicates are useful for dynamically breaking apart or constructing terms. The predicates functor/3 and arg/3 work together to create or analyze a term. The single predicate =../2 (univ) can also be used for the same purpose.
functor/3 works together with arg/3 (see below) to dynamically create or analyze a term. functor/3 gets the functor and arity of the term. arg/3 is used to get specific arguments.
If TERM is bound, then functor/3 unifies FUNCTOR and ARITY to the functor and arity.
Conversely, functor/3 will create a TERM with the specified FUNCTOR and ARITY with unbound variables for arguments.
?- functor(connect(yard, pen), F, A). F = connect A = 2 yes ?- functor(T, connect, 2), arg(1, T, yard), arg(2, T, pen). T = connect(yard, pen) yes
N must be instantiated to a positive integer less than or equal to the number of arguments in the compound term Term. Argument is then instantiated to the Nth argument of Term. arg/3 can be used to either find an argument or unify a value with an argument.
?- arg(1, connect(yard, pen), X). X = yard ?- arg(2, test(X,Y,Z), hello). X = H2 Y = hello Z = H4
The operator "=.." is called "univ." "Term =.. List" converts between compound terms Term and the list List. If Term is instantiated to a compound term, then List is unified with the list whose first element is the principal functor of Term, and whose successive elements are the arguments of Term. An atom is treated as a compound term of arity 0.
If Term is a variable, List must be instantiated to a list of definite length whose first element is an atom. Then Term is unified with the structure whose principal functor is the head of List and whose arguments are the elements in the tail of List.
univ fails if the arguments do not make legal structures.
?- T =.. [test, 1, 2, 3]. T = test(1,2,3) ?- test(1,2,3) =.. L. L = [test,1,2,3]
univ/2 is often used to dynamically generate goals for Prolog execution, as the following code sample illustrates. Note how unification caries the variables in the arguments to do/2 into the created GOAL, so they are properly instantiated by the call.
a(1). b(1,2). do(FUNCTOR, ARGS) :- GOAL =.. [FUNCTOR|ARGS], call(GOAL). ?- do(a, [X]). X = 1 yes ?- do(b, [X,Y]). X = 1 Y = 2 yes
gensym/2 is used to create atom names on the fly. The names are formed by adding successive integers to the root. gensym is designed to create new symbols each time it is called; it fails on backtracking. For example
?- gensym(foo, X). X = foo1 ?- gensym(foo, X). X = foo2 ?- gensym(foo, X). X = foo3
copy_term/2 unifies T2 with a copy of term T1. The copy is the same as the original, except it has new variables. This is useful for applications that want to work with a structure, but don't want to instantiate the variables of that structure.
?- copy_term(a(X), T). X = H1 T = a(H48) yes ?- A = a(X), copy_term(A, B), B = a(3). A = a(H1) X = H1 B = a(3) yes
string_query/2 takes as input a query in a string, QUERYSTRING, and returns a result string, RESULTSTRING, as a comma-separated list of variable name = binding pairs. An empty string is returned if there were no variables in the query string. string_query/2 is designed to make it easier to analyze the results of queries posed from the Logic Server API.
?- assert(pet(duck, leona)). yes ?- assert(pet(duck, ivan)). yes ?- string_query( `pet(Type, Name)`, ResultString ). ResultString = `Type = duck, Name = leona` ; ResultString = `Type = duck, Name = ivan` ; no ?-
varlist_query/3 takes as input a query in a string, QUERYSTRING, and returns a list of alternating variable names and bindings in RESULTLIST. The LENGTH of the list is returned in LENGTH. varlist_query/3 is intended to make it easy to get variable bindings in a query made from the Logic Server, but might be of use in other applications as well.
?- assert(pet(duck, leona)). yes ?- assert(pet(duck, ivan)). yes ?- varlist_query(`pet(X,Y)`, L, Z). L = 4 Z = ['X', duck, 'Y', leona] ; L = 4 Z = ['X', duck, 'Y', ivan] ; no ?-
numbervars/3 converts the variables of TERM into structures of the form, '$VAR'(N), that get special handling by write and writeq. They are displayed as _XN. This means they are written in a form that can be read back in as a variable. numbervars/3 is used internally in listing, to allow the clauses written out to be read back in without change.
START must be instantiated to a non-negative integer. END is instantiated to Start plus the number of distinct variables in Term.
In the following example, numbervars unifies X with '$VAR'(1) and Y with '$VAR'(2), which print out as _X1 and _X2.
?- T = a(X,Y), numbervars(T, 1, N), writeq(T). a(_X1, _X2) T = a(_X1, _X2) X = _X1 Y = _X2 N = 3 yes
varlist/1 returns a list of the variable names passed to the current clause. Each variable name is represented by a character list. This can be useful for applications that want to preserve and report on variable names. For example:
foo(A,B) :- varlist(L), write(L). ?- foo(XX,YYY). [[0w0058, 0w0058], [0w0059, 0w0059, 0w0059]] XX = H1 YYY = H2
varsof/2 succeeds if List can be unified with a list of all uninstantiated (and non-anonymous) variables in Term. Each variable occurs only once in List even though it may have more than one occurrence in Term.
?- varsof( a(X, Y, X), L). X = H0 Y = H1 L = [H0, H1]
Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.