@chapter SWI-Prolog Emulation

This library provides a number of SWI-Prolog builtins that are not by
default in YAP. This support is loaded with the
@code{expects_dialect(swi)} command.

@table @code

@item append(?@var{List1},?@var{List2},?@var{List3})
@findex swi_append/3
@snindex swi_append/3
@cnindex swi_append/3
Succeeds when @var{List3} unifies with the concatenation of @var{List1}
and @var{List2}. The predicate can be used with any instantiation
pattern (even three variables).

@item between(+@var{Low},+@var{High},?@var{Value})
@findex swi_between/3
@snindex swi_between/3
@cnindex swi_between/3

@var{Low} and @var{High} are integers, @var{High} less or equal than
@var{Low}. If @var{Value} is an integer, @var{Low} less or equal than
@var{Value} less or equal than @var{High}.  When @var{Value} is a
variable it is successively bound to all integers between @var{Low} and
@var{High}.  If @var{High} is @code{inf}, @code{between/3} is true iff
@var{Value} less or equal than @var{Low}, a feature that is particularly
interesting for generating integers from a certain value.

@item chdir(+@var{Dir})
@findex chdir/1
@snindex chdir/1
@cnindex chdir/1

Compatibility predicate.  New code should use @code{working_directory/2}.

@item concat_atom(+@var{List},-@var{Atom})
@findex concat_atom/2
@snindex concat_atom/2
@cnindex concat_atom/2

@var{List} is a list of atoms, integers or floating point numbers. Succeeds
if @var{Atom} can be unified with the concatenated elements of @var{List}. If
@var{List} has exactly 2 elements it is equivalent to @code{atom_concat/3},
allowing for variables in the list.

@item concat_atom(?@var{List},+@var{Separator},?@var{Atom})
@findex concat_atom/3
@snindex concat_atom/3
@cnindex concat_atom/3

Creates an atom just like concat_atom/2, but inserts @var{Separator}
between each pair of atoms.  For example:
@example
?- concat_atom([gnu, gnat], ', ', A).

A = 'gnu, gnat'
@end example

(Unimplemented) This predicate can also be used to split atoms by
instantiating @var{Separator} and @var{Atom}:

@example
?- concat_atom(L, -, 'gnu-gnat').

L = [gnu, gnat]
@end example

@item nth1(+@var{Index},?@var{List},?@var{Elem})
@findex swi_nth1/3
@snindex swi_nth1/3
@cnindex swi_nth1/3
Succeeds when the @var{Index}-th element of @var{List} unifies with
@var{Elem}. Counting starts at 1.

Set environment variable.  @var{Name} and @var{Value} should be
instantiated to atoms or integers.  The environment variable will be
passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}.
They also influence @code{expand_file_name/2}.

@item setenv(+@var{Name},+@var{Value})
@findex swi_setenv/2
@snindex swi_setenv/2
@cnindex swi_setenv/2
Set environment variable.  @var{Name} and @var{Value} should be
instantiated to atoms or integers.  The environment variable will be
passed to @code{shell/[0-2]} and can be requested using @code{getenv/2}.
They also influence @code{expand_file_name/2}.

@item term_to_atom(?@var{Term},?@var{Atom})
@findex swi_term_to_atom/2
@snindex swi_term_to_atom/2
@cnindex swi_term_to_atom/2
Succeeds if @var{Atom} describes a term that unifies with @var{Term}. When
@var{Atom} is instantiated @var{Atom} is converted and then unified with
@var{Term}.  If @var{Atom} has no valid syntax, a @code{syntax_error}
exception is raised. Otherwise @var{Term} is ``written'' on @var{Atom}
using @code{write/1}.

@item working_directory(-@var{Old},+@var{New})
@findex swi_working_directory/2
@snindex swi_working_directory/2
@cnindex swi_working_directory/2

Unify @var{Old} with an absolute path to the current working directory
and change working directory to @var{New}.  Use the pattern
@code{working_directory(CWD, CWD)} to get the current directory.  See
also @code{absolute_file_name/2} and @code{chdir/1}.

@item @@@var{Term1} =@@= @@@var{Term2}
@findex =@@=/2
@snindex =@@=/2
@cnindex =@@=/2

True iff @var{Term1} and @var{Term2} are structurally equivalent. I.e. if @var{Term1} and @var{Term2} are variants of each other.

@end table

@node Invoking Predicates on all Members of a List,Forall, , SWI-Prolog
@section Invoking Predicates on all Members of a List
@c \label{sec:applylist}

All the predicates in this section call a predicate on all members of a
list or until the predicate called fails.  The predicate is called via
@code{call/[2..]}, which implies common arguments can be put in
front of the arguments obtained from the list(s). For example:

@example
?- maplist(plus(1), [0, 1, 2], X).

X = [1, 2, 3]
@end example

we will phrase this as ``@var{Predicate} is applied on ...''

@table @code

@item maplist(+@var{Pred},+@var{List})
@findex swi_maplist/2
@snindex swi_maplist/2
@cnindex swi_maplist/2
@var{Pred} is applied successively on each element of @var{List} until
the end of the list or @var{Pred} fails. In the latter case 
@code{maplist/2} fails.

@item maplist(+@var{Pred},+@var{List1},+@var{List2})
@findex swi_maplist/3
@snindex swi_maplist/3
@cnindex swi_maplist/3
Apply @var{Pred} on all successive pairs of elements from
@var{List1} and
@var{List2}. Fails if @var{Pred} can not be applied to a
pair. See the example above.

@item maplist(+@var{Pred},+@var{List1},+@var{List2},+@var{List4})
@findex swi_maplist/4
@snindex swi_maplist/4
@cnindex swi_maplist/4
Apply @var{Pred} on all successive triples of elements from @var{List1},
@var{List2} and @var{List3}. Fails if @var{Pred} can not be applied to a
triple. See the example above.

@c @item findlist(+@var{Pred},+@var{List1},?@var{List2})
@c @findex findlist/3
@c @snindex findlist/3
@c @cnindex findlist/3
@c Unify @var{List2} with a list of all elements of @var{List1} to which
@c @var{Pred} applies.
@end table

@node Forall, ,Invoking Predicates on all Members of a List, SWI-Prolog
@section Forall			
@c \label{sec:forall2}

@table @code
@item forall(+@var{Cond},+@var{Action})
@findex swi_forall/2
@snindex swi_forall/2
@snindex swi_forall/2
@cnindex swi_forall/2

For all alternative bindings of @var{Cond} @var{Action} can be proven.
The next example verifies that all arithmetic statements in the list
@var{L} are correct. It does not say which is wrong if one proves wrong.

@example
?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]),
                 Result =:= Formula).
@end example

@end table

@node SWI-Prolog Global Variables,  Extensions, SWI-Prolog, Top
@chapter SWI Global variables
@c		\label{sec:gvar}

SWI-Prolog global variables are associations between names (atoms) and
terms.  They differ in various ways from storing information using
@code{assert/1} or @code{recorda/3}.

@itemize @bullet
@item The value lives on the Prolog (global) stack.  This implies 
          that lookup time is independent from the size of the term.
	  This is particulary interesting for large data structures
	  such as parsed XML documents or the CHR global constraint
	  store.

@item They support both global assignment using @code{nb_setval/2} and
          backtrackable assignment using @code{b_setval/2}.

@item Only one value (which can be an arbitrary complex Prolog
   	  term) can be associated to a variable at a time.

@item Their value cannot be shared among threads.  Each thread
          has its own namespace and values for global variables.

@item Currently global variables are scoped globally.  We may
          consider module scoping in future versions.
@end itemize

Both @code{b_setval/2} and @code{nb_setval/2} implicitly create a variable if the
referenced name does not already refer to a variable.

Global variables may be initialised from directives to make them
available during the program lifetime, but some considerations are
necessary for saved-states and threads. Saved-states to not store global
variables, which implies they have to be declared with @code{initialization/1}
to recreate them after loading the saved state.  Each thread has
its own set of global variables, starting with an empty set.  Using
@code{thread_inititialization/1} to define a global variable it will be
defined, restored after reloading a saved state and created in all
threads that are created @emph{after} the registration.


@table @code
@item b_setval(+@var{Name},+@var{Value})
@findex swi_b_setval/2
@snindex swi_b_setval/2
@cnindex swi_b_setval/2
Associate the term @var{Value} with the atom @var{Name} or replaces
the currently associated value with @var{Value}.  If @var{Name} does
not refer to an existing global variable a variable with initial value
@code{[]} is created (the empty list).  On backtracking the
assignment is reversed.

@item b_getval(+@var{Name},-@var{Value})
@findex swi_b_getval/2
@snindex swi_b_getval/2
@cnindex swi_b_getval/2
Get the value associated with the global variable @var{Name} and unify
it with @var{Value}. Note that this unification may further instantiate
the value of the global variable. If this is undesirable the normal
precautions (double negation or @code{copy_term/2}) must be taken. The
@code{b_getval/2} predicate generates errors if @var{Name} is not an atom or
the requested variable does not exist.

@item nb_setval(+@var{Name},+@var{Value})
@findex swi_nb_setval/2
@snindex swi_nb_setval/2
@cnindex swi_nb_setval/2
Associates a copy of @var{Value} created with @code{duplicate_term/2}
with the atom @var{Name}.  Note that this can be used to set an
initial value other than @code{[]} prior to backtrackable assignment.

@item nb_getval(+@var{Name},-@var{Value})
@findex swi_nb_getval/2
@snindex swi_nb_getval/2
@cnindex swi_nb_getval/2
The @code{nb_getval/2} predicate is a synonym for b_getval/2, introduced for
compatibility and symmetry.  As most scenarios will use a particular
global variable either using non-backtrackable or backtrackable
assignment, using @code{nb_getval/2} can be used to document that the 
variable is used non-backtrackable.

@c     \predicate{nb_linkval}{2}{+Name, +Value}
@c Associates the term @var{Value} with the atom @var{Name} without copying
@c it. This is a fast special-purpose variation of nb_setval/2 intended for
@c expert users only because the semantics on backtracking to a point
@c before creating the link are poorly defined for compound terms. The
@c principal term is always left untouched, but backtracking behaviour on
@c arguments is undone if the original assignment was \jargon{trailed} and
@c left alone otherwise, which implies that the history that created the
@c term affects the behaviour on backtracking. Please consider the
@c following example:

@c \begin{code}
@c demo_nb_linkval :-
@c 	T = nice(N),
@c 	(   N = world,
@c 	    nb_linkval(myvar, T),
@c 	    fail
@c 	;   nb_getval(myvar, V),
@c 	    writeln(V)
@c 	).
@c \end{code}

@item nb_current(?@var{Name},?@var{Value})
@findex swi_nb_current/2
@snindex swi_nb_current/2
@cnindex swi_nb_current/2
Enumerate all defined variables with their value. The order of
enumeration is undefined.

@item nb_delete(?@var{Name})
@findex nb_delete/1
@snindex nb_delete/1
@cnindex nb_delete/1
Delete the named global variable.
@end table

@section Compatibility of Global Variables

Global variables have been introduced by various Prolog
implementations recently.  YAP follows their implementation in SWI-Prolog, itself
based on hProlog by Bart Demoen. Jan and Bart
decided that the semantics if hProlog @code{nb_setval/2}, which is
equivalent to @code{nb_linkval/2} is not acceptable for normal Prolog
users as the behaviour is influenced by how builtin predicates
constructing terms (@code{read/1}, @code{=../2}, etc.) are implemented.

GNU-Prolog provides a rich set of global variables, including arrays.
Arrays can be implemented easily in SWI-Prolog using @code{functor/3} and
@code{setarg/3} due to the unrestricted arity of compound terms.


