1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8%
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License.
13%
14% The Original Code is  The ECLiPSe Constraint Logic Programming System.
15% The Initial Developer of the Original Code is  Cisco Systems, Inc.
16% Portions created by the Initial Developer are
17% Copyright (C) 1996 - 2006 Cisco Systems, Inc.  All Rights Reserved.
18%
19% Contributor(s):
20%
21% END LICENSE BLOCK
22%
23% @(#)umsarrays.tex     1.4
24%
25
26\chapter{Non-logical Storage and References}
27\label{chaparrays}
28%HEVEA\cutdef[1]{section}
29
30%----------------------------------------------------------------------
31\section{Introduction}
32%----------------------------------------------------------------------
33
34This chapter describes primitives that allow one to break the normal logic
35programming rules in two ways:
36\begin{itemize}
37\item information can be \emph{saved across logical failures} and backtracking;
38\item information can be accessed by \emph{naming} rather than by argument
39  passing.
40\end{itemize}
41Obviously, these facilities must be used with care and should always
42be encapsulated in an interface that provides logical semantics.
43
44ECLiPSe provides several facilities to store information across
45backtracking.  The following table gives an overview.  If at all
46possible, the handle-based facilities (bags, shelves and stores) should be
47preferred because they lead to cleaner, reentrant code (without global
48state) and reduce the risk of memory leaks.
49
50\vspace{2mm}
51\begin{center}
52\begin{tabular}{l|l l l}
53Facility & Type & Access & See \\
54\hline
55shelves&                array&          by handle&      shelf_create/2,3 \\
56bags&                   unordered bag&  by handle&      bag_create/1 \\
57stores&                 hash table&     by handle&      store_create/1 \\
58anonymous records&      ordered list&   by handle&      record_create/1 \\
59named shelves&          array&          by name&        shelf/2 \\
60named stores&           hash table&     by name&        store/1 \\
61non-logical variables&  single cell&    by name&        variable/1 \\
62non-logical arrays&     array&          by name&        array/1,2 \\
63records&                ordered list&   by name&        record/1,2 \\
64dynamic predicates&     ordered list&   by name&        dynamic/1, assert/1 \\
65\end{tabular}
66\end{center}
67\vspace{2mm}
68
69\index{reference}
70\index{global reference}
71The other facility described here, \emph{Global References}, does not store
72information across failure, but provides a means to give a name to
73an otherwise logical data structure. See section \ref{globrefs}.
74
75
76%----------------------------------------------------------------------
77\section{Bags}
78%----------------------------------------------------------------------
79
80A bag is an anonymous object which can be used to store
81information across failures.
82A bag is unordered and untyped. Any {\eclipse} term can be stored in a bag.
83Bags are referred to by a handle.
84An empty bag is created using
85\bipref{bag_create/1}{../bips/kernel/storage/bag_create-1.html},
86data is stored in the bag by invoking
87\bipref{bag_enter/2}{../bips/kernel/storage/bag_enter-2.html},
88and the stored data can be retrieved as a list with
89\bipref{bag_retrieve/2}{../bips/kernel/storage/bag_retrieve-2.html} or
90\bipref{bag_dissolve/2}{../bips/kernel/storage/bag_dissolve-2.html}.
91
92A typical application is the
93implementation of the \predspec{findall/3} predicate or similar functionality.
94As opposed to the use of \predspec{record/2} or \predspec{assert/1}, the
95solution using
96bags is more efficient, more robust, and trivially reentrant.
97\begin{verbatim}
98    simple_findall(Goal, Solutions) :-
99        bag_create(Bag),
100        (
101            call(Goal),
102            bag_enter(Bag, Goal),
103            fail
104        ;
105            true
106        ),
107        bag_dissolve(Bag, Solutions).
108\end{verbatim}
109
110
111%----------------------------------------------------------------------
112\section{Shelves}
113%----------------------------------------------------------------------
114
115A \defnotion{shelf} is an anonymous object which can be used to store information
116across failures.  A typical application is counting of solutions,
117keeping track of the best solution, aggregating information across
118multiple solutions, etc.
119
120A shelf is an object with multiple slots whose contents survive
121backtracking.  The content of each slot can be set and retrieved
122individually, or the whole shelf can be retrieved as a term.
123
124Shelves are referred to by handle, not by name, so they make it easy
125to write robust, reentrant code.  A shelf disappears when the system
126backtracks over its creation, when the shelf handle gets garbage
127collected, or when it is explicitly destroyed.
128
129A shelf is initialized using
130\bipref{shelf_create/2}{../bips/kernel/storage/shelf_create-2.html} or
131\bipref{shelf_create/3}{../bips/kernel/storage/shelf_create-3.html}.
132Data is stored in the slots (or the shelf as a whole) with
133\bipref{shelf_set/3}{../bips/kernel/storage/shelf_set-3.html}
134and retrieved with
135\bipref{shelf_get/3}{../bips/kernel/storage/shelf_get-3.html}.
136
137Example: Counting how many solutions a goal has:
138\begin{verbatim}
139    count_solutions(Goal, Total) :-
140        shelf_create(count(0), Shelf),
141        (
142            call(Goal),
143            shelf_get(Shelf, 1, Old),
144            New is Old + 1,
145            shelf_set(Shelf, 1, New),
146            fail
147        ;
148            shelf_get(Shelf, 1, Total)
149        ).
150\end{verbatim}
151In this particular example, we could have used
152\bipref{shelf_inc/2}{../bips/kernel/storage/shelf_inc-2.html} to
153increment the counter.
154
155
156%----------------------------------------------------------------------
157\section{Stores}
158%----------------------------------------------------------------------
159
160
161\index{hash table}
162A \defnotion{store} is an anonymous object which can be used to store information
163across failures.  A typical application is aggregating information across
164multiple solutions.  Note that, if it is not necessary to save information
165across backtracking, the use of the
166\bipref{library(hash)}{../bips/lib/hash/index.html}
167is more appropriate and efficient than the facilities described here.
168
169A store is a hash table which can store arbitrary terms under arbitrary
170ground keys. Modifications of a store, as well as the entries within it,
171survive backtracking.  The basic operations on stores are entering and
172looking up information under a key, or retrieving the store contents as
173a whole.
174
175Stores come in two flavours:  anonymous stores are created with
176\bipref{store_create/1}{../bips/kernel/storage/store_create-1.html}
177and referred to by handle, while named stores are created with a
178\bipref{store/ 1}{../bips/kernel/storage/store-1.html}
179declaration and referred to by their name within a module.
180If possible, anonymous stores should be preferred because they make it
181easier to write robust, reentrant code.  For example, an anonymous store
182automatically disappears when the system backtracks over its creation,
183or when the store handle gets garbage collected.  Named stores, on the
184other hand, must be explicitly destroyed in order to free the
185associated memory.
186
187Data is entered into a store using
188\bipref{store_set/3}{../bips/kernel/storage/store_set-3.html}
189and retrieved using
190\bipref{store_get/3}{../bips/kernel/storage/store_get-3.html}.
191It is also possible to retrieve information: either all keys with
192\bipref{stored_keys/2}{../bips/kernel/storage/stored_keys-2.html},
193or the full contents of the table with
194\bipref{stored_keys_and_values/2}{../bips/kernel/storage/stored_keys_and_values-2.html}.
195Entries can be deleted via
196\bipref{store_delete/2}{../bips/kernel/storage/store_delete-2.html} or
197\bipref{store_erase/1}{../bips/kernel/storage/store_erase-1.html}.
198
199\index{memoization}
200\index{Fibonacci}
201\indextt{fib/2}
202A typical use of stores is for the implementation of memoization.
203The following is an implementation of the Fibonacci function, which
204uses a store to remember previously computed results.
205It consists of the declaration of a named store, a wrapper predicate
206\predspec{fib/2} that handles storage and lookup of results, and the standard
207recursive definition \predspec{fib_naive/2}:
208\begin{verbatim}
209    :- local store(fib).
210
211    fib(N, F) :-
212        ( store_get(fib, N, FN) ->
213            F = FN                    % use a stored result
214        ;
215            fib_naive(N, F),
216            store_set(fib, N, F)      % store computed result
217        ).
218
219    fib_naive(0, 0).
220    fib_naive(1, 1).
221    fib_naive(N, F) :-
222        N1 is N-1, N2 is N-2,
223        fib(N1, F1), fib(N2, F2),
224        F is F1 + F2.
225\end{verbatim}
226Using this definition, large function values can be efficiently computed:
227\begin{verbatim}
228    ?- fib(300, F).
229    F = 222232244629420445529739893461909967206666939096499764990979600
230    Yes (0.00s cpu)
231\end{verbatim}
232
233
234
235The next example shows the use of an anonymous store, for computing
236how many solutions of each kind a goal has.
237The store is used to maintain counter values, using the
238solution term as the key to distinguish the different counters:
239\begin{verbatim}
240    solutions_profile(Sol, Goal, Profile) :-
241        store_create(Store),
242        (
243            call(Goal),
244            store_inc(Store, Sol),
245            fail
246        ;
247            stored_keys_and_values(Store, Profile)
248        ).
249\end{verbatim}
250Running this code produces for example:
251\begin{verbatim}
252    ?- solutions_profile(X, member(X, [a, b, c, b, a, b]), R).
253    X = X
254    R = [a - 2, b - 3, c - 1]
255    Yes (0.00s cpu)
256\end{verbatim}
257
258
259%----------------------------------------------------------------------
260\section{Non-logical Variables}
261%----------------------------------------------------------------------
262\index{non-logical variable}\index{variable!non-logical}
263Non-logical variables in {\eclipse} are a means of storing a copy
264of a Prolog term under a name (an atom).
265The atom is the \defnotionni{name} and the associated
266term is the \defnotionni{value} of the non-logical variable.
267This term may be of any form, whether an integer or a huge compound
268structure.
269Note that the associated term is being copied and so if it is not ground,
270the retrieved term is not strictly identical to the stored one
271but is a \emph{variant} of it\footnote{%
272  Though this feature could be used to make a copy of a term with new variables,
273  it is cleaner and more efficient to use
274  \bipref{copy_term/2}{../bips/kernel/termmanip/copy_term-2.html} for that
275  purpose}.
276There are two fundamental operations that can be performed on a non-logical
277variable:
278setting the variable (giving it a value), and referencing the variable
279(finding the value currently associated with it).
280
281The value of a non-logical variable is set using the
282\bipref{setval/2}{../bips/kernel/storage/setval-2.html}
283predicate.
284This has the format
285\begin{quote}
286\preddef{setval(\pattern{Name},~\pattern{Value})}\indextt{setval/2}
287\end{quote}
288For instance, the goal
289\begin{quote}
290\begin{verbatim}
291setval(firm, 3)
292\end{verbatim}
293\end{quote}
294gives the non-logical variable \about{firm} the value 3.
295The value of a non-logical variable is retrieved using the
296\bipref{getval/2}{../bips/kernel/storage/getval-2.html}
297predicate.
298
299The goal
300\begin{quote}
301\begin{verbatim}
302getval(firm, X)
303\end{verbatim}
304\end{quote}
305will unify \about{X} to
306the value of the non-logical variable \about{firm}, which has been previously
307set by
308\bipref{setval/2}{../bips/kernel/storage/setval-2.html}.
309If no value has been previously set, the call raises an exception.
310If the value of a non-logical variable is an integer, the predicates
311\bipref{incval/1}{../bips/kernel/storage/incval-1.html}
312and \bipref{decval/1}{../bips/kernel/storage/decval-1.html}
313may be used toincrement and decrement the value of the
314variable, respectively.
315The predicates \bipref{incval/1}{../bips/kernel/storage/incval-1.html} and
316\bipref{decval/1}{../bips/kernel/storage/decval-1.html} may be used e.g., in a
317failure-driven loop to provide
318an incremental count across failures as in the example:
319\begin{quote}
320\begin{verbatim}
321count_solutions(Goal, _) :-
322        setval(count, 0),
323        call(Goal),
324        incval(count),
325        fail.
326count_solutions(_, N) :-
327        getval(count, N).
328\end{verbatim}
329\end{quote}
330However, code like this should be used carefully.
331Apart from being a non-logical feature, it also causes the code to be
332not reentrant. That is, if \predspec{count_solutions/2} were called recursively
333from
334inside \about{Goal}, this would smash the counter and yield incorrect
335results.\footnote{%
336  A similar problem can occur when the counter is used by an interrupt handler.}
337
338The visibility of a non-logical variable is local to the module
339where it is first set. It is good style to declare them using
340\bipref{local/1}{../bips/kernel/modules/local-1.html}
341\bipref{variable/1}{../bips/kernel/storage/variable-1.html}
342declarations. For example, in the above example one should use
343\begin{quote}
344\begin{verbatim}
345:- local variable(count).
346\end{verbatim}
347\end{quote}
348If it is necessary to access the value of a variable in other modules,
349exported access predicates should be provided.
350
351
352%----------------------------------------------------------------------
353\section{Non-logical Arrays}
354%----------------------------------------------------------------------
355\index{non-logical array}\index{array!non-logical}
356Non-logical arrays are a generalisation of the non-logical variable, capable of
357storing
358multiple values.
359An array has to be declared in advance.
360It has a fixed number of dimensions and a fixed size in each dimension.
361Arrays in {\eclipse} are managed solely by special predicates.
362In these predicates, arrays are represented by compound terms, e.g.,
363\notation{matrix(5, 8)}
364where \about{matrix} is the name of the array, the arity of 2 specifies
365the number of dimensions, and the integers 5 and 8 specify the size
366in each dimension. The number of elements this array can hold is
367thus 5*8 = 40.
368The elements of this array can be addressed from \notation{matrix(0, 0)}
369up to \notation{matrix(4, 7)}.
370
371An array must be explicitly created using a
372\bipref{local/1}{../bips/kernel/modules/local-1.html}
373\bipref{array/1}{../bips/kernel/storage/array-1.html}
374declaration, e.g.,
375\begin{quote}
376\begin{verbatim}
377:- local array(matrix(5, 8)).
378\end{verbatim}
379\end{quote}
380The array is only accessible from within the module where it was declared.
381The declaration will create a two-dimensional, 5-by-8 array with 40 elements
382\notation{matrix(0, 0)} to \notation{matrix(4, 7)}.
383Arrays can be  erased using the predicate
384\bipref{erase_array/1}{../bips/kernel/storage/erase_array-1.html},
385e.g.,
386\begin{quote}
387\begin{verbatim}
388erase_array(matrix/2).
389\end{verbatim}
390\end{quote}
391
392The value of an element of the array is set using the
393\bipref{setval/2}{../bips/kernel/storage/setval-2.html}
394predicate. The first argument of
395\bipref{setval/2}{../bips/kernel/storage/setval-2.html} specifies the element
396which is
397to be set, the second specifies the value to assign to it.
398The goal
399\begin{quote}
400\begin{verbatim}
401setval(matrix(3, 2), plato)
402\end{verbatim}
403\end{quote}
404sets the value
405of element (3, 2) of array \about{matrix} to the atom \about{plato}.
406Similarly, values of array elements are retrieved by use of the
407\bipref{getval/2}{../bips/kernel/storage/getval-2.html}
408predicate. The first argument of
409\bipref{getval/2}{../bips/kernel/storage/getval-2.html} specifies the element to
410be
411referenced, the second is unified with the value of that element.
412Thus if the value of \notation{matrix(3, 2)} had been set as above, the goal
413\begin{quote}
414\begin{verbatim}
415getval(matrix(3, 2), Val)
416\end{verbatim}
417\end{quote}
418would unify \about{Val} with the atom \about{plato}.
419Similarly to non-logical variables, the value of integer array elements
420can be updated using \bipref{incval/1}{../bips/kernel/storage/incval-1.html} and
421\bipref{decval/1}{../bips/kernel/storage/decval-1.html}.
422
423It is possible to declare arrays whose elements are
424constrained to belong to certain types. This allows {\eclipse} to increase
425time and space efficiency of array element manipulation.
426Such an array is created for instance by the predicate
427\begin{quote}
428\begin{verbatim}
429:- local array(primes(100),integer).
430\end{verbatim}
431\end{quote}
432The second argument specifies the type of the elements of the array.
433It takes as value an atom from the
434list {\tt float} (for floating point numbers),
435{\tt integer} (for integers), {\tt byte} (an integer modulo 256),
436or {\tt prolog} (any Prolog term---the resulting array is the
437same as if no type was specified).
438When a typed array is created, the value of each element is initialized to zero
439in the case of {\tt byte}, {\tt integer} and {\tt float}, and to
440an uninstantiated variable in the case of {\tt prolog}.
441Whenever a typed array element is set, type checking is carried out.
442
443As an example of the use of a typed array, consider the following goal, which
444creates a 3-by-3 matrix describing a 90 degree rotation about the x-axis of
445a Cartesian coordinate system.
446\begin{quote}
447\begin{verbatim}
448:- local array(rotate(3, 3), integer).
449:- setval(rotate(0, 0), 1),
450   setval(rotate(1, 2), -1),
451   setval(rotate(2, 1), 1).
452\end{verbatim}
453\end{quote}
454(The other elements of the above array are automatically initialized to zero).
455
456The predicate
457\bipref{current_array/2}{../bips/kernel/storage/current_array-2.html}
458is provided to find the size, type and visibility of defined arrays.
459of the array and its type to be found:
460\begin{quote}
461\preddef{current_array(\pattern{Array},~\pattern{Props})}
462\end{quote}
463where \about{Array} is the array specification as in the declaration (but it
464may be uninstantiated or partially instantiated), and \about{Props} is
465a list indicating the array's type and visibility.
466Non-logical variables are also returned: \about{Array} is then an atom, and
467the type is \notation{prolog}.
468\begin{quote}
469\begin{verbatim}
470[eclipse 1]: local(array(pair(2))),
471        setval(count, 3),
472        local(array(count(3,4,5), integer)).
473
474yes.
475[eclipse 2]: current_array(Array, Props).
476
477Array = pair(2)
478Props = [prolog, local]     More? (;)
479
480Array = count
481Props = [prolog, local]     More? (;)
482
483Array = count(3, 4, 5)
484Props = [integer, local]     More? (;)
485
486no (more) solution.
487[eclipse 3]: current_array(count(X,Y,Z), _).
488
489X = 3
490Y = 4
491Z = 5
492yes.
493\end{verbatim}
494\end{quote}
495
496
497%----------------------------------------------------------------------
498\section{Global References}
499%----------------------------------------------------------------------
500\label{globrefs}
501Terms stored in non-logical variables and arrays are copies of the
502\bipref{setval/2}{../bips/kernel/storage/setval-2.html} arguments,
503and the terms obtained by
504\bipref{getval/2}{../bips/kernel/storage/getval-2.html} are thus not identical
505to the original terms, in particular their variables are different.
506Sometimes it is necessary to be able
507to access the original term with its variables, i.e., to have
508\emph{global variables} in the meaning of conventional programming
509languages.
510A typical example is global state that a set of predicates wants to
511share without having to pass an argument pair through all the
512predicate invocations.
513
514{\eclipse} offers the possibility to store references to general terms
515and to access them even inside predicates that have no common variables
516with the predicate that has stored them.
517They are stored in so-called \defnotioni{references}{reference}.%
518\index{global reference}
519For example,
520\begin{quote}
521\begin{verbatim}
522:- local reference(p).
523\end{verbatim}
524\end{quote}
525or
526\begin{quote}
527\begin{verbatim}
528:- local reference(p, 0).
529\end{verbatim}
530\end{quote}
531creates a named reference \about{p} (with an initial value of 0)
532which can be used to store references to terms.
533This reference is accessed and modified in the same way as non-logical
534variables,
535with \bipref{setval/2}{../bips/kernel/storage/setval-2.html}
536and \bipref{getval/2}{../bips/kernel/storage/getval-2.html},
537but the following points are different for references:
538\begin{itemize}
539\item the accessed term is identical to the stored term (with its current
540substitutions):
541\begin{quote}
542\begin{verbatim}
543[eclipse 1]: local reference(a), variable(b).
544
545yes.
546[eclipse 2]: Term = p(X), setval(a, Term), getval(a, Y), Y == Term.
547X = X
548Y = p(X)
549Term = p(X)
550yes.
551[eclipse 3]: Term = p(X), setval(b, Term), getval(b, Y), Y == Term.
552
553no (more) solution.
554\end{verbatim}
555\end{quote}
556
557\item the modifications are backtrackable, when the execution fails
558over the \bipref{setval/2}{../bips/kernel/storage/setval-2.html} call, the
559previous value of the global reference is restored
560
561\begin{quote}
562\begin{verbatim}
563[eclipse 4]: setval(a, 1), (setval(a, 2), getval(a, X); getval(a, Y)).
564X = 2
565Y = Y     More? (;)
566
567X = X
568Y = 1
569\end{verbatim}
570\end{quote}
571
572\item there are no arrays of references, but the same effect can be
573achieved by storing a structure in a reference and using the structure's
574arguments. The arguments can then be accessed and modified using
575\bipref{arg/3}{../bips/kernel/termmanip/arg-3.html} and
576\bipref{setarg/3}{../bips/kernel/termmanip/setarg-3.html} respectively.
577\end{itemize}
578
579%There is only a limited number of references available and their
580%use should be considered very carefully.
581The use of references should be considered carefully.
582Their overuse can lead to programs which are
583difficult to understand and difficult to optimize.
584Typical applications use at most a single reference per module,
585for example to hold state that would otherwise have to be passed
586via additional arguments through many predicate invocations.
587
588%HEVEA\cutend
589