Non-logical Variables

## 9.5 Non-logical Variables

Non-logical variables in ECLiPSe are a means of storing a copy of a Prolog term under a name (an atom). The atom is the name and the associated term is the value of the non-logical variable. This term may be of any form, whether an integer or a huge compound structure. Note that the associated term is being copied and so if it is not ground, the retrieved term is not strictly identical to the stored one but is a variant of it1. There are two fundamental operations that can be performed on a non-logical variable: setting the variable (giving it a value), and referencing the variable (finding the value currently associated with it).
The value of a non-logical variable is set using the setval/2 predicate. This has the format

> setval(Name, Value)

For instance, the goal

>     setval(firm, 3)

gives the non-logical variable firm the value 3. The value of a non-logical variable is retrieved using the getval/2 predicate. The goal

>     getval(firm, X)

will unify X to the value of the non-logical variable firm, which has been previously set by setval/2. If no value has been previously set, the call raises an exception. If the value of a non-logical variable is an integer, the predicates incval/1 and decval/1 may be used to increment and decrement the value of the variable, respectively. The predicates incval/1 and decval/1 may be used e.g. in a failure-driven loop to provide an incremental count across failures as in the example:

>     count_solutions(Goal, _) :-
>             setval(count, 0),
>             call(Goal),
>             incval(count),
>             fail.
>     count_solutions(_, N) :-
>             getval(count, N).

However, code like this should be used carefully. Apart from being a non-logical feature, it also causes the code to be not reentrant. I.e. if count_solutions/2 would be called recursively from inside `Goal`, this would smash the counter and yield incorrect results2.
The visibility of a non-logical variable is local to the module where it is first set. It is good style to declare them using local/1 variable/1 declarations. E.g. in the above example one should use

>     :- local variable(count).

If it is necessary to access the value of a variable in other modules, exported access predicates should be provided.