326 lines
11 KiB
TeX
326 lines
11 KiB
TeX
@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.
|
|
|
|
|