Previous Contents Next
6.21 Global variables

GNU Prolog provides a simple and powerful way to assign and read global variables. There are 3 kinds of objects which can be associated to a global variable:

The initial value of a global variable is the integer 0. A global variable is referenced by a name (i.e. name = an atom) possibly indexed if it is an array (i.e. name = a compound term). In the following, GVarName represents such a reference to a global variable and its syntax is as follows:

GVarName ::= atom
    atom(Index,...,Index)
Index ::= integer
    GVarName
When a GVarName is used as an index, the value of this variable must be an integer. Indexes range from 0 to Size-1 if the array has Size elements. The space necessary for copies and arrays are dynamically allocated and recovered as soon as possible. For instance, when an atom is associated to a global variable whose current value is an array, the space for this array is recovered (unless the assignment is to be undone when backtracking occurs).

Arrays: the predicates g_assign/2, g_assignb/2 and g_link/2 (section 6.21.1) define an array when the assigned value is a compound term with principal functor g_array. Then an array is assigned to GVarName. There are 3 forms for the term g_array:

The compound term with principal functor g_array_extend can be used instead of g_array to modify the structure of a (possibly) existing array. In that case, the existing elements of the array are not initialized.

When an array is read, a term of the form g_array([Elem0,..., ElemSize-1]) is returned.

6.21.1 g_assign/2, g_assignb/2, g_link/2

Templates

g_assign(+callable_term, ?term)
g_assignb(+callable_term, ?term)
g_link(+callable_term, ?term)
Description

g_assign(GVarName, Value) assigns a copy of the term Value to GVarName. This assignment is not undone when backtracking occurs.

g_assignb/2 is similar to g_assign/2 but the assignment is undone at backtracking.

g_link(GVarName, Value) makes a link between GVarName to the term Value. This allows the user to give a name to any Prolog term (in particular non-ground terms). Such an assignment is always undone when backtracking occurs (since the term may no longer exist). If Value is an atom or an integer, g_link/2 and g_assignb/2 have the same behavior. Since g_link/2 only handles links to existing terms it does not require extra memory space and is not expensive in terms of execution time.

Errors

GVarName is a variable    instantiation_error
GVarName is neither a variable nor a callable term    type_error(callable, GVarName)
GVarName is a compound term and a sub-argument E is not a valid index (section 6.21)    domain_error(g_array_index, E)

Portability

GNU Prolog predicates.

6.21.2 g_read/2

Templates

g_read(+callable_term, ?term)
Description

g_read(GVarName, Value) unifies Value with the term assigned to GVarName.

Errors

GVarName is a variable    instantiation_error
GVarName is neither a variable nor a callable term    type_error(callable, GVarName)
GVarName is a compound term and a sub-argument E is not a valid index (section 6.21)    domain_error(g_array_index, E)

Portability

GNU Prolog predicate.

6.21.3 g_array_size/2

Templates

g_array_size(+callable_term, ?integer)
Description

g_array_size(GVarName, Value) unifies Size with the dimension (an integer > 0) of the array assigned to GVarName. Fails if GVarName is not an array.

Errors

GVarName is a variable    instantiation_error
GVarName is neither a variable nor a callable term    type_error(callable, GVarName)
GVarName is a compound term and a sub-argument E is not a valid index (section 6.21)    domain_error(g_array_index, E)
Size is neither a variable nor an integer    type_error(integer, Size)

Portability

GNU Prolog predicate.

6.21.4 Examples

A simple counter: the following predicate defines a counter using a global variable:

inc(Var, Value) :-
        g_read(Var, Value),
        X is Value+1,
        g_assign(Var, X).
The query: inc(c, X) will succeed unifying X with 0, another call to inc(a, Y) will then unify Y with 1, and so on.

Difference between g_assign/2 and g_assignb/2: g_assign/2 does not undo its assignment when backtracking occurs whereas g_assignb/2 undoes it.

test(Old) :-    testb(Old) :-
        g_assign(x,1),            g_assign(x,1),
        (   g_read(x, Old),            (   g_read(x, Old),
            g_assign(x, 2)                g_assignb(x, 2)
        ;   g_read(x, Old),            ;   g_read(x, Old),
            g_assign(x, 3)                g_assign(x, 3)
        ).            ).
The query test(Old) will succeed unifying Old with 1 and on backtracking with 2 (i.e. the assignment of the value 2 has not been undone). The query testb(Old) will succeed unifying Old with 1 and on backtracking with 1 (i.e. the assignment of the value 2 has been undone).

Difference between g_assign/2 and g_link/2: g_assign/2 (and g_assignb/2) creates a copy of the term whereas g_link/2 does not. g_link/2 can be used to avoid passing big data structures (e.g. dictionaries,...) as arguments to predicates.

test(B) :-    test(B) :-
        g_assign(b, f(X)),            g_link(b, f(X)),
        X=12,            X=12,
        g_read(b, B).            g_read(b, B).
The query test(B) will succeed unifying B with f(_) (g_assign/2 assigns a copy of the value). The query testl(B) will succeed unifying B with f(12) (g_link/2 assigns a pointer to the term).

Simple array definition: here are some queries to show how arrays can be handled:

| ?- g_assign(w, g_array(3)), g_read(w, X).

X = g_array([0,0,0])

| ?- g_assign(w(0), 16), g_assign(w(1), 32), g_assign(w(2), 64), g_read(w, X).

X = g_array([16,32,64])
this is equivalent to:

| ?- g_assign(k, g_array([16,32,64])), g_read(k, X).

X = g_array([16,32,64])

| ?- g_assign(k, g_array(3,null)), g_read(k, X), g_array_size(k, S).

S = 3
X = g_array([null,null,null])
2-D array definition:

| ?- g_assign(w, g_array(2, g_array(3))), g_read(w, X).

X = g_array([g_array([0,0,0]),g_array([0,0,0])])

| ?- (   for(I,0,1), for(J,0,2), K is I*3+J, g_assign(w(I,J), K),
         fail
     ;   g_read(w, X)
     ).

X = g_array([g_array([0,1,2]),g_array([3,4,5])])

| ?- g_read(w(1),X).

X = g_array([3,4,5])
Hybrid array:

| ?- g_assign(w,g_array([1,2,g_array([a,b,c]), g_array(2,z),5])), g_read(w, X).

X = g_array([1,2,g_array([a,b,c]), g_array([z,z]),5])

| ?- g_read(w(1), X), g_read(w(2,1), Y), g_read(w(3,1), Z).

X = 2
Y = b
Z = z

| ?- g_read(w(1,2),X).

{exception: error(domain_error(g_array_index,w(1,2)),g_read/2)}
Array extension:

| ?- g_assign(a, g_array([10,20,30])), g_read(a, X).

X = g_array([10,20,30])

| ?- g_assign(a, g_array_extend(5,null)), g_read(a, X).

X = g_array([10,20,30,null,null])

| ?- g_assign(a, g_array([10,20,30])), g_read(a, X).

X = g_array([10,20,30])

| ?- g_assign(a, g_array_extend([1,2,3,4,5,6])), g_read(a, X).

X = g_array([10,20,30,4,5,6])

Copyright (C) 1999,2000 Daniel Diaz

Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.

More about the copyright
Previous Contents Next