### 9.3.1 Types of Terms

Remember what we said about terms in Prolog in the very first lecture. We saw that there are different kinds of terms, namely variables, atoms, numbers and complex terms and what they look like. Furthermore, we said that atoms and numbers are grouped together under the name constants and constants and variables constitute the simple terms. The following picture summarizes this:

Sometimes it is useful to know of which type a given term is. You might, for instance, want to write a predicate that has to deal with different kinds of terms, but has to treat them in different ways. Prolog provides a couple of built-in predicates that test whether a given term is of a certain type. Here they are:

 `atom/1` Tests whether the argument is an atom. `integer/1` Tests whether the argument is an integer, such as `4`, `10`, or `-6`. `float/1` Tests whether the argument is a floating point number, such as `1.3` or `5.0`. `number/1` Tests whether the argument is a number, i.e. an integer or a float `atomic/1` Tests whether the argument is a constant. `var/1` Tests whether the argument is uninstantiated. `nonvar/1` Tests whether the argument is instantiated.

So, let's see how they behave.

`?- atom(a).yes?- atom(7).no?- atom(loves(vincent,mia)).no`

These three examples for the behavior of `atom/1` is pretty much what one would expect of a predicate for testing whether a term is an atom. But what happens, when we call `atom/1` with a variable as argument?

`?- atom(X).no`

This makes sense, since an uninstantiated variable is not an atom. If we, however, instantiate `X` with an atom first and then ask `atom(X)`, Prolog answers `yes'.

`?- X = a, atom(X).X = ayes`

But it is important that the instantiation is done before the test:

`?- atom(X), X = a.no`

`number/1`, `integer/1`, and `float/1` behave analogously. Try it!

`atomic/1` tests whether a given term is a constant, i.e. whether it is either an atom or a number. So `atomic/1` will evaluate to true whenever either `atom/1` or `number/1` evaluate to true and it fails when both of them fail.

`?- atomic(mia).yes?- atomic(8).yes?- atomic(loves(vincent,mia)).no?- atomic(X)no`

Finally there are two predicates to test whether the argument is an uninstantiated or instantiated variable. So:

`?- var(X)yes?- var(loves(vincent,mia)).no?- nonvar(loves(vincent,mia)).yes?- nonvar(X).no`

Note that a complex term which contains uninstantiated variables, is of course not an uninstantiated variable itself (but a complex term). Therefore:

`?- var(loves(_,mia)).no?- nonvar(loves(_,mia)).yes`

And again, when the variable `X` gets instantiated `var(X)` and `nonvar(X)` behave differently depending on whether they are called before or after the instantiation.

`?- X = a, var(X).no?- var(X), X = a.X = ayes`

Patrick Blackburn, Johan Bos and Kristina Striegnitz
Version 1.2.5 (20030212)