d8d4d1516d
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1678 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
12911 lines
423 KiB
TeX
12911 lines
423 KiB
TeX
\input texinfo @c -*- mode: texinfo; coding: latin-1; -*-
|
||
|
||
@c %**start of header
|
||
@setfilename yap.info
|
||
@setcontentsaftertitlepage
|
||
@settitle YAP Prolog User's Manual
|
||
@c For double-sided printing, uncomment:
|
||
@c @setchapternewpage odd
|
||
@c %**end of header
|
||
|
||
@set VERSION 5.1.2
|
||
@set EDITION 4.2.4
|
||
@set UPDATED December 2004
|
||
|
||
@c Index for C-Prolog compatible predicate
|
||
@defindex cy
|
||
@c Index for predicates not in C-Prolog
|
||
@defindex cn
|
||
@c Index for predicates sort of (almost) in C-Prolog
|
||
@defindex ca
|
||
|
||
@c Index for SICStus Prolog compatible predicate
|
||
@defindex sy
|
||
@c Index for predicates not in SICStus Prolog
|
||
@defindex sn
|
||
@c Index for predicates sort of (almost) in SICStus Prolog
|
||
@defindex sa
|
||
|
||
|
||
@setchapternewpage odd
|
||
@c @smallbook
|
||
@comment %** end of header
|
||
|
||
@ifnottex
|
||
@format
|
||
@dircategory The YAP Prolog System
|
||
@direntry
|
||
* Yap: (yap). YAP Prolog User's Manual.
|
||
@end direntry
|
||
@end format
|
||
@end ifnottex
|
||
|
||
@titlepage
|
||
@title YAP User's Manual
|
||
@subtitle Version @value{VERSION}
|
||
@author V@'{@dotless{i}}tor Santos Costa,
|
||
@author Lu@'{@dotless{i}}s Damas,
|
||
@author Rog@'erio Reis, and
|
||
@author R@'uben Azevedo
|
||
@page
|
||
@vskip 2pc
|
||
Copyright @copyright{} 1989-2000 L. Damas, V. Santos Costa and Universidade
|
||
do Porto.
|
||
|
||
Permission is granted to make and distribute verbatim copies of
|
||
this manual provided the copyright notice and this permission notice
|
||
are preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
manual under the conditions for verbatim copying, provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this manual
|
||
into another language, under the above conditions for modified versions.
|
||
|
||
@end titlepage
|
||
|
||
@ifnottex
|
||
@node Top, , , (dir)
|
||
@top YAP Prolog
|
||
|
||
This file documents the YAP Prolog System version @value{VERSION}, a
|
||
high-performance Prolog compiler developed at LIACC, Universidade do
|
||
Porto. YAP is based on David H. D. Warren's WAM (Warren Abstract
|
||
Machine), with several optimizations for better performance. YAP follows
|
||
the Edinburgh tradition, and is largely compatible with DEC-10 Prolog,
|
||
Quintus Prolog, and especially with C-Prolog.
|
||
|
||
This file contains extracts of the SWI-Prolog manual, as written by Jan
|
||
Wielemaker. Our thanks to the author for his kind permission in allowing
|
||
us to include his text in this document.
|
||
|
||
@menu
|
||
* Intro:: Introduction
|
||
* Install:: Installation
|
||
* Run:: Running YAP
|
||
* Syntax:: The syntax of YAP
|
||
* Loading Programs:: Loading Prolog programs
|
||
* Modules:: Using Modules in YAP
|
||
* Builtins:: Built In Predicates
|
||
* Library:: Library Predicates
|
||
* SWI-Prolog:: SWI-Prolog emulation
|
||
* Extensions:: Extensions to Standard YAP
|
||
* Rational Trees:: Working with Rational Trees
|
||
* Coroutining:: Changing the Execution of Goals
|
||
* Attributed Variables:: Using attributed Variables
|
||
* CLPR:: The CLP(R) System
|
||
* CHR:: The CHR System
|
||
* Logtalk:: The Logtalk Object-Oriented System
|
||
* Threads:: Thread Library
|
||
* Parallelism:: Running in Or-Parallel
|
||
* Tabling:: Storing Intermediate Solutions of programs
|
||
* Low Level Profiling:: Profiling Abstract Machine Instructions
|
||
* Low Level Tracing:: Tracing at Abstract Machine Level
|
||
* Debugging:: Using the Debugger
|
||
* Efficiency:: Efficiency Considerations
|
||
* C-Interface:: Interfacing predicates written in C
|
||
* YapLibrary:: Using YAP as a library in other programs
|
||
* Compatibility:: Compatibility with other Prolog systems
|
||
* Predicate Index:: An item for each predicate
|
||
* Concept Index:: An item for each concept
|
||
|
||
Built In Predicates
|
||
* Control:: Controlling the execution of Prolog programs
|
||
* Undefined Procedures:: Handling calls to Undefined Procedures
|
||
* Testing Terms:: Predicates on Terms
|
||
* Comparing Terms:: Comparison of Terms
|
||
* Arithmetic:: Arithmetic in YAP
|
||
* I/O:: Input/Output with YAP
|
||
* Database:: Modifying Prolog's Database
|
||
* Sets:: Finding All Possible Solutions
|
||
* Grammars:: Grammar Rules
|
||
* Preds:: Predicate Information
|
||
* OS:: Access to Operating System Functionality
|
||
* Term Modification:: Updating Prolog Terms
|
||
* Profiling:: Profiling Prolog Execution
|
||
* Call Counting:: Limiting the Maximum Number of Reductions
|
||
* Arrays:: Supporting Global and Local Arrays
|
||
* Preds:: Information on Predicates
|
||
* Misc:: Miscellaneous Predicates
|
||
|
||
|
||
Subnodes of Running
|
||
* Running Yap Interactively:: Interacting with Yap
|
||
* Running Prolog Files:: Running Prolog files as scripts
|
||
|
||
Subnodes of Syntax
|
||
* Formal Syntax:: Syntax of Terms
|
||
* Tokens:: Syntax of Prolog tokens
|
||
|
||
Subnodes of Tokens
|
||
* Numbers:: Integer and Floating-Point Numbers
|
||
* Strings:: Sequences of Characters
|
||
* Atoms:: Atomic Constants
|
||
* Variables:: Logical Variables
|
||
* Punctuation Tokens:: Tokens that separate other tokens
|
||
* Layout:: Comments and Other Layout Rules
|
||
|
||
Subnodes of Numbers
|
||
* Integers:: How Integers are read and represented
|
||
* Floats:: Floating Point Numbers
|
||
|
||
Subnodes of Loading Programs
|
||
* Compiling:: Program Loading and Updating
|
||
* Setting the Compiler:: Changing the compiler's parameters
|
||
* Saving:: Saving and Restoring Programs
|
||
|
||
Subnodes of Modules
|
||
* Module Concepts:: The Key Ideas in Modules
|
||
* Defining Modules:: How To Define a New Module
|
||
* Using Modules:: How to Use a Module
|
||
* Meta-Predicates in Modules:: How to Handle New Meta-Predicates
|
||
|
||
Subnodes of Input/Output
|
||
* Streams and Files:: Handling Streams and Files
|
||
* C-Prolog File Handling:: C-Prolog Compatible File Handling
|
||
* I/O of Terms:: Input/Output of terms
|
||
* I/O of Characters:: Input/Output of Characters
|
||
* I/O for Streams:: Input/Output using Streams
|
||
* C-Prolog to Terminal:: C-Prolog compatible Character I/O to terminal
|
||
* I/O Control:: Controlling your Input/Output
|
||
* Sockets:: Using Sockets from YAP
|
||
|
||
Subnodes of Database
|
||
* Modifying the Database:: Asserting and Retracting
|
||
* Looking at the Database:: Finding out what is in the Data Base
|
||
* Database References:: Using Data Base References
|
||
* Internal Database:: YAP's Internal Database
|
||
* BlackBoard:: Storing and Fetching Terms in the BlackBoard
|
||
|
||
Subnodes of Library
|
||
* Apply Macros:: Apply a Predicate to a list or to sub-terms.
|
||
* Association Lists:: Binary Tree Implementation of Association Lists.
|
||
* AVL Trees:: Predicates to add and lookup balanced binary trees.
|
||
* Heaps:: Labelled binary tree where the key of each node is less
|
||
than or equal to the keys of its children.
|
||
* Lists:: List Manipulation
|
||
* Ordered Sets:: Ordered Set Manipulation
|
||
* Pseudo Random:: Pseudo Random Numbers
|
||
* Queues:: Queue Manipulation
|
||
* Random:: Random Numbers
|
||
* Read Utilities:: SWI inspired utilities for fast stream scanning.
|
||
* Red-Black Trees:: Predicates to add, lookup and delete in red-black binary trees.
|
||
* RegExp:: Regular Expression Manipulation
|
||
* Splay Trees:: Splay Trees
|
||
* String I/O:: Writing To and Reading From Strings
|
||
* System:: System Utilities
|
||
* Terms:: Utilities on Terms
|
||
* Cleanup:: Call With registered Cleanup Calls
|
||
* Timeout:: Call With Timeout
|
||
* Trees:: Updatable Binary Trees
|
||
* UGraphs:: Unweighted Graphs
|
||
* DGraphs:: Directed Graphs Implemented With Red-Black Trees
|
||
* UnDGraphs:: Undirected Graphs Using DGraphs
|
||
* LAM:: LAM MPI
|
||
|
||
|
||
Subnodes of Debugging
|
||
* Deb Preds:: Debugging Predicates
|
||
* Deb Interaction:: Interacting with the debugger
|
||
|
||
Subnodes of Compatibility
|
||
* C-Prolog:: Compatibility with the C-Prolog interpreter
|
||
* SICStus Prolog:: Compatibility with the Quintus and SICStus Prolog systems
|
||
* ISO Prolog:: Compatibility with the ISO Prolog standard
|
||
|
||
Subnodes of Attributes
|
||
* Attribute Declarations:: Declaring New Attributes
|
||
* Attribute Manipulation:: Setting and Reading Attributes
|
||
* Attributed Unification:: Tuning the Unification Algorithm
|
||
* Displaying Attributes:: Displaying Attributes in User-Readable Form
|
||
* Projecting Attributes:: Obtaining the Attributes of Interest
|
||
* Attribute Examples:: Two Simple Examples of how to use Attributes.
|
||
|
||
Subnodes of SWI-Prolog
|
||
* Invoking Predicates on all Members of a List :: maplist and friends
|
||
* Forall :: forall built-in
|
||
* hProlog and SWI-Prolog Attributed Variables :: Emulating SWI-like attributed variables
|
||
* SWI-Prolog Global Variables :: Emulating SWI-like attributed variables
|
||
|
||
@c Subnodes of CLP(Q,R)
|
||
@c * Introduction to CLPQ:: The CLP(Q,R) System
|
||
@c * Referencing CLPQR:: How to Reference CLP(Q,R)
|
||
@c * CLPQR Acknowledgments:: Acknowledgments for CLP(Q,R)
|
||
@c * Solver Interface:: Using the CLP(Q,R) System
|
||
@c * Notational Conventions:: The CLP(Q,R) Notation
|
||
@c * Solver Predicates:: The CLP(Q,R) Interface Predicates
|
||
@c * Unification:: Unification and CLP(Q,R)
|
||
@c * Feedback and Bindings:: Information flow in CLP(Q,R)
|
||
@c * Linearity and Nonlinear Residues:: Linear and Nonlinear Constraints
|
||
@c * How Nonlinear Residues are made to disappear:: Handling Nonlinear Residues
|
||
@c * Isolation Axioms:: Isolating the Variable to be Solved
|
||
@c * Numerical Precision and Rationals:: Reals and Rationals
|
||
@c * Projection and Redundancy Elimination:: Presenting Bindings for Query Variables
|
||
@c * Variable Ordering:: Linear Relationships between Variables
|
||
@c * Turning Answers into Terms:: using @code{call_residue/2}
|
||
@c * Projecting Inequalities:: How to project linear inequations
|
||
@c * Why Disequations:: Using Disequations in CLP(Q,R)
|
||
@c * Syntactic Sugar:: An easier syntax
|
||
@c * Monash Examples:: The Monash Library
|
||
@c * Compatibility Notes:: CLP(Q,R) and the clp(R) interpreter
|
||
@c * A Mixed Integer Linear Optimization Example:: MIP models
|
||
@c * Implementation Architecture:: CLP(Q,R) Components
|
||
@c * Fragments and Bits:: Final Last Words on CLP(Q,R)
|
||
@c * CLPQR Bugs:: Bugs in CLP(Q,R)
|
||
@c * CLPQR References:: References for CLP(Q,R)
|
||
|
||
Subnodes of CLPR
|
||
* CLPR Solver Predicates::
|
||
* CLPR Syntax::
|
||
* CLPR Unification::
|
||
* CLPR Non-linear Constraints::
|
||
|
||
Subnodes of CHR
|
||
* CHR Introduction::
|
||
* CHR Syntax and Semantics::
|
||
* CHR in YAP Programs::
|
||
* CHR Debugging::
|
||
* CHR Examples::
|
||
* CHR Compatibility::
|
||
* CHR Guidelines::
|
||
|
||
Subnodes of C-Interface
|
||
* Manipulating Terms:: Primitives available to the C programmer
|
||
* Unifying Terms:: How to Unify Two Prolog Terms
|
||
* Manipulating Strings:: From character arrays to Lists of codes and back
|
||
* Memory Allocation:: Stealing Memory From Yap
|
||
* Controlling Streams:: Control How Yap sees Streams
|
||
* Calling Yap From C:: From C to Yap to C to Yap
|
||
* Writing C:: Writing Predicates in C
|
||
* Loading Objects:: Loading Object Files
|
||
* Sav&Rest:: Saving and Restoring
|
||
* Yap4 Notes:: Changes in Foreign Predicates Interface
|
||
|
||
Subnodes of C-Prolog
|
||
* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog
|
||
* Fully C-Prolog Compatible:: Yap predicates fully compatible with
|
||
C-Prolog
|
||
* Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog
|
||
* Not in C-Prolog:: Yap predicates not available in C-Prolog
|
||
* Not in YAP:: C-Prolog predicates not available in YAP
|
||
|
||
Subnodes of SICStus Prolog
|
||
* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog
|
||
* Fully SICStus Compatible:: Yap predicates fully compatible with
|
||
SICStus Prolog
|
||
* Not Strictly SICStus Compatible:: Yap predicates not strictly as
|
||
SICStus Prolog
|
||
* Not in SICstus Prolog:: Yap predicates not available in SICStus Prolog
|
||
|
||
|
||
Tables
|
||
* Operators:: Predefined operators
|
||
|
||
@end menu
|
||
|
||
@end ifnottex
|
||
|
||
|
||
@node Intro, Install, , Top
|
||
@unnumbered Introduction
|
||
|
||
This document provides User information on version @value{VERSION} of
|
||
YAP (@emph{yet another prolog}). The YAP Prolog System is a
|
||
high-performance Prolog compiler developed at LIACC, Universidade do
|
||
Porto. YAP provides several important features:
|
||
|
||
@itemize @bullet
|
||
@item Speed: YAP is widely considered one of the fastest available Prolog
|
||
systems.
|
||
|
||
@item Functionality: it supports stream I/O, sockets, modules,
|
||
exceptions, Prolog debugger, C-interface, dynamic code, internal
|
||
database, DCGs, saved states, co-routining, arrays.
|
||
|
||
@item We explicitly allow both commercial and non-commercial use of YAP.
|
||
@end itemize
|
||
|
||
YAP is based on the David H. D. Warren's WAM (Warren Abstract Machine),
|
||
with several optimizations for better performance. YAP follows the
|
||
Edinburgh tradition, and was originally designed to be largely
|
||
compatible with DEC-10 Prolog, Quintus Prolog, and especially with
|
||
C-Prolog.
|
||
|
||
YAP implements most of the ISO-Prolog standard. We are striving at
|
||
full compatibility, and the manual describes what is still
|
||
missing. The manual also includes a (largely incomplete) comparison
|
||
with SICStus Prolog.
|
||
|
||
The document is intended neither as an introduction to Prolog nor to the
|
||
implementation aspects of the compiler. A good introduction to
|
||
programming in Prolog is the book @cite{The Art of Prolog}, by
|
||
L. Sterling and E. Shapiro, published by "The MIT Press, Cambridge
|
||
MA". Other references should include the classical @cite{Programming in
|
||
Prolog}, by W.F. Clocksin and C.S. Mellish, published by
|
||
Springer-Verlag.
|
||
|
||
YAP 4.3 is known to build with many versions of gcc (<= gcc-2.7.2, >=
|
||
gcc-2.8.1, >= egcs-1.0.1, gcc-2.95.*) and on a variety of Unixen:
|
||
SunOS 4.1, Solaris 2.*, Irix 5.2, HP-UX 10, Dec Alpha Unix, Linux 1.2
|
||
and Linux 2.* (RedHat 4.0 thru 5.2, Debian 2.*) in both the x86 and
|
||
alpha platforms. It has been built on Windows NT 4.0 using Cygwin from
|
||
Cygnus Solutions (see README.nt) and using Visual C++ 6.0.
|
||
|
||
The overall copyright and permission notice for YAP4.3 can be found in
|
||
the Artistic file in this directory. YAP follows the Perl Artistic
|
||
license, and it is thus non-copylefted freeware.
|
||
|
||
If you have a question about this software, desire to add code, found a
|
||
bug, want to request a feature, or wonder how to get further assistance,
|
||
please send e-mail to @email{yappers@@ncc.up.pt}. To subscribe to the
|
||
mailing list, send a request to @email{majordomo@@ncc.up.pt} with body
|
||
"subscribe yappers".
|
||
|
||
Online documentation is available for YAP at:
|
||
|
||
@url{http://www.ncc.up.pt/~vsc/Yap/}
|
||
|
||
Recent versions of Yap, including both source and selected binaries,
|
||
can be found from this same URL.
|
||
|
||
This manual was written by V@'{@dotless{i}}tor Santos Costa,
|
||
Lu@'{@dotless{i}}s Damas, Rog@'erio Reis, and R@'uben Azevedo. The
|
||
manual is largely based on the DECsystem-10 Prolog User's Manual by
|
||
D.L. Bowen, L. Byrd, F. C. N. Pereira, L. M. Pereira, and
|
||
D. H. D. Warren. We have also used comments from the Edinburgh Prolog
|
||
library written by R. O'Keefe. We would also like to gratefully
|
||
acknowledge the contributions from Ashwin Srinivasian.
|
||
|
||
We are happy to include in YAP several excellent packages developed
|
||
under separate licenses. Our thanks to the authors for their kind
|
||
authorization to include these packages.
|
||
|
||
The packages are, in alphabetical order:
|
||
|
||
@itemize @bullet
|
||
@item The CHR package developed by Tom Schrijvers,
|
||
Christian Holzbaur, and Jan Wielemaker.
|
||
|
||
@item The CLP(R) package developed Leslie De Koninck, Bart Demoen, Tom
|
||
Schrijvers and Jan Wielemaker and based on the CLP(Q,R) implementation
|
||
by Christian Holzbauer.
|
||
|
||
@item The Logtalk Object-Oriented system is developed at the University
|
||
of Beira Interior, Portugal, by Paulo Moura.
|
||
The package is distributed under the Perl Artistic License.
|
||
Instructions about loading this package are included in this document.
|
||
The documentation on this package (including full installation instructions)
|
||
is distributed separately from yap.tex.
|
||
|
||
Copyright @copyright{} 1998-2006 Paulo Moura
|
||
|
||
@item The Pillow WEB library developed at Universidad Politecnica de
|
||
Madrid by the CLIP group. This package is distributed under the FSF's
|
||
LGPL. Documentation on this package is distributed separately from
|
||
yap.tex.
|
||
|
||
@item The yap2swi library implements some of the functionality of
|
||
SWI's PL interface. Please do refer to the SWI-Prolog home page:
|
||
|
||
@url{http://www.swi-prolog.org}
|
||
|
||
for more information on SWI-Prolog and for a detailed description of its
|
||
foreign interface.
|
||
|
||
@end itemize
|
||
|
||
@node Install, Run, Intro, Top
|
||
@chapter Installing YAP
|
||
@cindex installation
|
||
|
||
|
||
@menu
|
||
* Configuration Options:: Tuning the Functionality of YAP Machine
|
||
* Machine Options:: Tuning YAP for a Particular Machine and Compiler
|
||
@end menu
|
||
|
||
To compile YAP it should be sufficient to:
|
||
|
||
@enumerate
|
||
@item @code{mkdir ARCH}.
|
||
|
||
@item @code{cd ARCH}.
|
||
|
||
@item @code{../configure ...options...}.
|
||
|
||
Notice that by default @code{configure} gives you a vanilla
|
||
configuration. For instance, in order to use coroutining and/or CLP
|
||
you need to do
|
||
|
||
@example
|
||
../configure --enable-coroutining ...options...
|
||
@end example
|
||
Please @pxref{Configuration Options} for extra options.
|
||
|
||
@item check the Makefile for any extensions or changes you want to
|
||
make.
|
||
|
||
YAP uses @code{autoconf}. Recent versions of Yap try to follow GNU
|
||
conventions on where to place software.
|
||
|
||
@itemize @bullet
|
||
@item The main executable is placed at @code{BINDIR}. This executable is
|
||
actually a script that calls the Prolog engine, stored at @code{LIBDIR}.
|
||
|
||
@item @code{LIBDIR} is the directory where libraries are stored. YAPLIBDIR is a
|
||
subdirectory that contains the Prolog engine and a Prolog library.
|
||
|
||
@item @code{INCLUDEDIR} is used if you want to use Yap as a library.
|
||
|
||
@item @code{INFODIR} is where to store @code{info} files. Usually
|
||
@code{/usr/local/info}, @code{/usr/info}, or @code{/usr/share/info}.
|
||
@end itemize
|
||
|
||
@item @code{make}.
|
||
|
||
@item If the compilation succeeds, try @code{./yap}.
|
||
|
||
@item If you feel satisfied with the result, do @code{make install}.
|
||
|
||
@item @code{make install-info} will create the info files in the
|
||
standard info directory.
|
||
|
||
@item @code{make html} will create documentation in html format in the
|
||
predefined directory.
|
||
|
||
In most systems you will need to be superuser in order to do @code{make
|
||
install} and @code{make info} on the standard directories.
|
||
@end enumerate
|
||
|
||
@node Configuration Options, Machine Options, ,Install
|
||
@section Tuning the Functionality of YAP
|
||
@cindex syntax
|
||
|
||
Compiling Yap with the standard options give you a plain vanilla
|
||
Prolog. You can tune Yap to include extra functionality by calling
|
||
@code{configure} with the appropriate options:
|
||
|
||
@itemize @bullet
|
||
@item @code{--enable-rational-trees=yes} gives you support for infinite
|
||
rational trees.
|
||
|
||
@item @code{--enable-coroutining=yes} gives you support for coroutining,
|
||
including freezing of goals, attributed variables, and
|
||
constraints. This will also enable support for infinite rational
|
||
trees.
|
||
|
||
@item @code{--enable-depth-limit=yes} allows depth limited evaluation, say for
|
||
implementing iterative deepening.
|
||
|
||
@item @code{--enable-low-level-tracer=yes} allows support for tracing all calls,
|
||
retries, and backtracks in the system. This can help in debugging your
|
||
application, but results in performance loss.
|
||
|
||
@item @code{--enable-wam-profile=yes} allows profiling of abstract machine
|
||
instructions. This is useful when developing YAP, should not be so
|
||
useful for normal users.
|
||
|
||
@item @code{--enable-condor=yes} allows using the Condor system that
|
||
support High Throughput Computing (HTC) on large collections of
|
||
distributively owned computing resources.
|
||
|
||
@item @code{--enable-tabling=yes} allows tabling support. This option
|
||
is still experimental.
|
||
|
||
@item @code{--enable-parallelism=@{env-copy,sba,a-cow@}} allows
|
||
or-parallelism supported by one of these three forms. This option is
|
||
still highly experimental.
|
||
|
||
@item @code{--with-gmp[=DIR]} give a path to where one can find the
|
||
@code{GMP} library if not installed in the default path.
|
||
|
||
|
||
@item @code{--enable-threads} allows using of the multi-threading
|
||
predicates provided by YAP. Depending on the operating system, the
|
||
option @code{--enable-pthread-locking} may also need to be used.
|
||
|
||
@end itemize
|
||
|
||
Next section discusses machine dependent details.
|
||
|
||
@node Machine Options, , Configuration Options,Install
|
||
@section Tuning YAP for a Particular Machine and Compiler
|
||
@cindex machine optimizations
|
||
|
||
The default options should give you best performance under
|
||
@code{GCC}. Although the system is tuned for this compiler
|
||
we have been able to compile versions of Yap under lcc in Linux,
|
||
Sun's cc compiler, IBM's xlc, SGI's cc, and Microsoft's Visual C++
|
||
6.0.
|
||
|
||
@menu
|
||
* Tuning for GCC:: Using the GNUCC compiler
|
||
* Compiling Under Visual C++:: Using Microsoft's Visual C++ environment
|
||
* Tuning for SGI cc:: Compiling Under SGI's @code{cc}
|
||
@end menu
|
||
|
||
|
||
@node Tuning for GCC, Compiling Under Visual C++, , Machine Options
|
||
@section Tuning YAP for @code{GCC}.
|
||
|
||
Yap has been developed to take advantage of @code{GCC} (but not to
|
||
depend on it). The major advantage of @code{GCC} is threaded code and
|
||
explicit register reservation.
|
||
|
||
YAP is set by default to compile with the best compilation flags we
|
||
know. Even so, a few specific options reduce portability. The option
|
||
@itemize @bullet
|
||
@item @code{--enable-max-performance=yes} will try to support the best
|
||
available flags for a specific architectural model. Currently, the option
|
||
assumes a recent version of @code{GCC}.
|
||
@item @code{--enable-debug-yap} compiles Yap so that it can be debugged
|
||
by tools such as @code{dbx} or @code{gdb}.
|
||
@end itemize
|
||
|
||
Here follow a few hints:
|
||
|
||
On x86 machines the flags:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -DBP_FREE=1
|
||
@end example
|
||
|
||
tells us to use the @code{%bp} register (frame-pointer) as the emulator's
|
||
program counter. This seems to be stable and is now default.
|
||
|
||
On Sparc/Solaris2 use:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -mno-app-regs -DOPTIMISE_ALL_REGS_FOR_SPARC=1
|
||
@end example
|
||
|
||
and YAP will get two extra registers! This trick does not work on
|
||
SunOS 4 machines.
|
||
|
||
Note that versions of GCC can be tweaked to recognize different
|
||
processors within the same instruction set, e.g. 486, Pentium, and
|
||
PentiumPro for the x86; or Ultrasparc, and Supersparc for
|
||
Sparc. Unfortunately, some of these tweaks do may make Yap run slower or
|
||
not at all in other machines with the same instruction set, so they
|
||
cannot be made default.
|
||
|
||
Last, the best options also depends on the version of GCC you are using, and
|
||
it is a good idea to consult the GCC manual under the menus "Invoking
|
||
GCC"/"Submodel Options". Specifically, you should check
|
||
@code{-march=XXX} for recent versions of GCC/EGCS. In the case of
|
||
@code{GCC2.7} and other recent versions of @code{GCC} you can check:
|
||
|
||
@table @code
|
||
|
||
@item 486:
|
||
In order to take advantage of 486 specific optimizations in GCC 2.7.*:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -m486 -DBP_FREE=1
|
||
@end example
|
||
|
||
@item Pentium:
|
||
@example
|
||
YAP_EXTRAS= ... -m486 -malign-loops=2 -malign-jumps=2 \
|
||
-malign-functions=2
|
||
@end example
|
||
|
||
@item PentiumPro and other recent Intel and AMD machines:
|
||
PentiumPros are known not to require alignment. Check your version of
|
||
@code{GCC} for the best @code{-march} option.
|
||
|
||
@item Super and UltraSparcs:
|
||
@example
|
||
YAP_EXTRAS= ... -msupersparc
|
||
@end example
|
||
|
||
@item MIPS: if have a recent machine and you need a 64 bit wide address
|
||
space you can use the abi 64 bits or eabi option, as in:
|
||
@example
|
||
CC="gcc -mabi=64" ./configure --...
|
||
@end example
|
||
Be careful. At least for some versions of @code{GCC}, compiling with
|
||
@code{-g} seems to result in broken code.
|
||
|
||
@item WIN32: GCC is distributed in the MINGW32 and CYGWIN packages.
|
||
|
||
The Mingw32 environment is available from the URL:
|
||
|
||
@code{http://www.mingw.org}
|
||
|
||
You will need to install the @code{msys} and @code{mingw}
|
||
packages. You should be able to do configure, make and make install.
|
||
|
||
If you use mingw32 you may want to search the contributed packages for
|
||
the @code{gmp} multi-precision arithmetic library. If you do setup Yap
|
||
with @code{gmp} note that @code{libgmp.dll} must be in the path,
|
||
otherwise Yap will not be able to execute.
|
||
|
||
CygWin environment is available from the URL:
|
||
|
||
@code{http://www.cygwin.com}
|
||
|
||
@noindent
|
||
and mirrors. We suggest using recent versions of the cygwin shell. The
|
||
compilation steps under the cygwin shell are as follows:
|
||
|
||
@example
|
||
mkdir cyg
|
||
$YAPSRC/configure --enable-coroutining \\
|
||
--enable-depth-limit \\
|
||
--enable-max-performance
|
||
make
|
||
make install
|
||
@end example
|
||
|
||
By default, Yap will use the @code{--enable-cygwin=no} option to
|
||
disable the use of the cygwin dll and to enable the mingw32 subsystem
|
||
instead. Yap thus will not need the cygwin dll. It instead accesses
|
||
the system's @code{CRTDLL.DLL} @code{C} run time library supplied with
|
||
Win32 platforms through the mingw32 interface. Note that some older
|
||
WIN95 systems may not have @code{CRTDLL.DLL}, in this case it should
|
||
be sufficient to import the file from a newer WIN95 or WIN98 machine.
|
||
|
||
You should check the default installation path which is set to
|
||
@code{/Yap} in the standard Makefile. This string will usually
|
||
be expanded into @code{c:\Yap} by Windows.
|
||
|
||
The cygwin environment does not provide @t{gmp}. You can fetch a dll for
|
||
the @t{gmp} library from @url{http://www.sf.net/projects/mingwrep}.
|
||
|
||
It is also possible to configure Yap to be a part of the cygwin
|
||
environment. In this case you should use:
|
||
@example
|
||
mkdir cyg
|
||
$YAPSRC/configure --enable-coroutining \\
|
||
--enable-max-performance \\
|
||
--enable-cygwin=yes
|
||
make
|
||
make install
|
||
@end example
|
||
Yap will then compile using the cygwin library and will be installed
|
||
in cygwin's @code{/usr/local}. You can use Yap from a cygwin console,
|
||
or as a standalone application as long as it can find
|
||
@code{cygwin1.dll} in its path.
|
||
|
||
@end table
|
||
|
||
@node Compiling Under Visual C++, Tuning for SGI cc, Tuning for GCC, Machine Options
|
||
@subsection Compiling Under Visual C++
|
||
|
||
Yap compiles cleanly under Microsoft's Visual C++ release 6.0. We next
|
||
give a step-by-step tutorial on how to compile Yap manually using this
|
||
environment.
|
||
|
||
First, it is a good idea to build Yap as a DLL:
|
||
|
||
@enumerate
|
||
|
||
@item create a project named yapdll using File.New. The project will be a
|
||
DLL project, initially empty.
|
||
|
||
Notice that either the project is named yapdll or you must replace the
|
||
preprocessors variable @var{YAPDLL_EXPORTS} to match your project names
|
||
in the files @code{YapInterface.h} and @code{c_interface.c}.
|
||
|
||
@item add all .c files in the @var{$YAPSRC/C} directory and in the
|
||
@var{$YAPSRC\OPTYap} directory to the Project's @code{Source Files} (use
|
||
FileView).
|
||
|
||
@item add all .h files in the @var{$YAPSRC/H} directory,
|
||
@var{$YAPSRC\include} directory and in the @var{$YAPSRC\OPTYap}
|
||
subdirectory to the Project's @code{Header Files}.
|
||
|
||
@item Ideally, you should now use @code{m4} to generate extra .h from .m4 files and use
|
||
@code{configure} to create a @code{config.h}. Or, you can be lazy, and
|
||
fetch these files from @var{$YAPSRC\VC\include}.
|
||
|
||
@item You may want to go to @code{Build.Set Active Configuration} and set @code{Project
|
||
Type} to @code{Release}
|
||
|
||
@item To use Yap's own include directories you have to set the Project
|
||
option @code{Project.Project Settings.C/C++.Preprocessor.Additional
|
||
Include Directories} to include the directories @var{$YAPSRC\H},
|
||
@var{$YAPSRC\VC\include}, @var{$YAPSRC\OPTYap} and
|
||
@var{$YAPSRC\include}. The syntax is:
|
||
|
||
@example
|
||
$YAPSRC\H, $YAPSRC\VC\include, $YAPSRC\OPTYap, $YAPSRC\include
|
||
@end example
|
||
|
||
@item Build: the system should generate an @code{yapdll.dll} and an @code{yapdll.lib}.
|
||
|
||
@item Copy the file @code{yapdll.dll} to your path. The file
|
||
@code{yapdll.lib} should also be copied to a location where the linker can find it.
|
||
@end enumerate
|
||
|
||
Now you are ready to create a console interface for Yap:
|
||
@enumerate
|
||
@item create a second project say @code{wyap} with @code{File.New}. The project will be a
|
||
WIN32 console project, initially empty.
|
||
|
||
@item add @var{$YAPSRC\console\yap.c} to the @code{Source Files}.
|
||
|
||
@item add @var{$YAPSRC\VC\include\config.h} and the files in @var{$YAPSRC\include} to
|
||
the @code{Header Files}.
|
||
|
||
@item You may want to go to @code{Build.Set Active Configuration} and set
|
||
@code{Project Type} to @code{Release}.
|
||
|
||
@item you will eventually need to bootstrap the system by booting from
|
||
@code{boot.yap}, so write:
|
||
|
||
@example
|
||
-b $YAPSRC\pl\boot.yap
|
||
@end example
|
||
|
||
in @code{Project.Project Settings.Debug.Program Arguments}.
|
||
|
||
@item You need the sockets and yap libraries. Add
|
||
|
||
@example
|
||
ws2_32.lib yapdll.lib to
|
||
@end example
|
||
|
||
to
|
||
|
||
to @code{Project.Project Settings.Link.Object/Library Modules}
|
||
|
||
You may also need to set the @code{Link Path} so that VC++ will find @code{yapdll.lib}.
|
||
|
||
@item set @code{Project.Project Settings.C/C++.Preprocessor.Additional
|
||
Include Directories} to include the @var{$YAPSRC/VC/include} and
|
||
@var{$YAPSRC/include}.
|
||
|
||
The syntax is:
|
||
|
||
@example
|
||
$YAPSRC\VC\include, $YAPSRC\include
|
||
@end example
|
||
|
||
@item Build the system.
|
||
|
||
@item Use @code{Build.Start Debug} to boot the system, and then create the saved state with
|
||
|
||
@example
|
||
['$YAPSRC\\pl\\init'].
|
||
save_program(startup).
|
||
^Z
|
||
@end example
|
||
|
||
That's it, you've got Yap and the saved state!
|
||
@end enumerate
|
||
|
||
The $YAPSRC\VC directory has the make files to build Yap4.3.17 under VC++ 6.0.
|
||
|
||
@node Tuning for SGI cc, , Compiling Under Visual C++ ,Machine Options
|
||
@subsection Compiling Under SGI's cc
|
||
|
||
YAP should compile under the Silicon Graphic's @code{cc} compiler,
|
||
although we advise using the GNUCC compiler, if available.
|
||
|
||
@table @code
|
||
@item 64 bit
|
||
Support for 64 bits should work by using (under Bourne shell syntax):
|
||
@example
|
||
CC="cc -64" $YAP_SRC_PATH/configure --...
|
||
@end example
|
||
@end table
|
||
|
||
@node Run, Syntax, Install, Top
|
||
@chapter Running YAP
|
||
|
||
@menu
|
||
* Running Yap Interactively:: Interacting with Yap
|
||
* Running Prolog Files:: Running Prolog files as scripts
|
||
@end menu
|
||
|
||
@cindex booting
|
||
We next describe how to invoke Yap in Unix systems.
|
||
|
||
@node Running Yap Interactively, ,Running Prolog Files,Run
|
||
@section Running Yap Interactively
|
||
|
||
Most often you will want to use Yap in interactive mode. Assuming that
|
||
YAP is in the user's search path, the top-level can be invoked under
|
||
Unix with the following command:
|
||
|
||
@example
|
||
yap [-s n] [-h n] [-a n] [-c IP_HOST port ] [filename]
|
||
@end example
|
||
|
||
@noindent
|
||
All the arguments and flags are optional and have the following meaning:
|
||
@table @code
|
||
@item -?
|
||
print a short error message.
|
||
@item -s @var{n}
|
||
allocate @var{n} K bytes for local and global stacks
|
||
@item -h @var{n}
|
||
allocate @var{n} K bytes for heap and auxiliary stacks
|
||
@item -t @var{n}
|
||
allocate @var{n} K bytes for the trail stack
|
||
@item -l @var{YAP_FILE}
|
||
compile the Prolog file @var{YAP_FILE} before entering the top-level.
|
||
@item -L @var{YAP_FILE}
|
||
compile the Prolog file @var{YAP_FILE} and then halt. This option is
|
||
useful for implementing scripts.
|
||
@item -g @var{Goal}
|
||
run the goal @var{Goal} before top-level. The goal is converted from
|
||
an atom to a Prolog term.
|
||
@item -z @var{Goal}
|
||
run the goal @var{Goal} as top-level. The goal is converted from
|
||
an atom to a Prolog term.
|
||
@item -b @var{BOOT_FILE}
|
||
boot code is in Prolog file @var{BOOT_FILE}. The filename must define
|
||
the predicate '$live'/0.
|
||
@item -c @t{IP_HOST} @t{port}
|
||
connect standard streams to host @t{IP_HOST} at port @t{port}
|
||
@item filename
|
||
restore state saved in the given file
|
||
@item --
|
||
separator for arguments to Prolog code. These arguments are visible
|
||
through the unix/1 built-in.
|
||
@end table
|
||
|
||
Note that YAP will output an error message on the following conditions:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a file name was given but the file does not exist or is not a saved
|
||
YAP state;
|
||
@item
|
||
the necessary amount of memory could not be allocated;
|
||
@item
|
||
the allocated memory is not enough to restore the state.
|
||
@end itemize
|
||
|
||
When restoring a saved state, YAP will allocate the
|
||
same amount of memory as that in use when the state was saved, unless a
|
||
different amount is specified by flags in the command line. By default,
|
||
YAP restores the file @samp{startup} from the current directory or from
|
||
the YAP library.
|
||
@cindex environment variables
|
||
|
||
@findex YAPBINDIR
|
||
@itemize @bullet
|
||
@item
|
||
YAP usually boots from a saved state. The saved state will use the default
|
||
installation directory to search for the YAP binary unless you define
|
||
the environment variable YAPBINDIR.
|
||
|
||
@findex YAPLIBDIR
|
||
@item
|
||
YAP always tries to find saved states from the current directory
|
||
first. If it cannot it will use the environment variable YAPLIBDIR, if
|
||
defined, or search the default library directory.
|
||
|
||
@findex YAPSHAREDIR
|
||
@item
|
||
YAP will try to find library files from the YAPSHAREDIR/library
|
||
directory.
|
||
@end itemize
|
||
|
||
@node Running Prolog Files, Running Yap Interactively, , Run
|
||
@section Running Prolog Files
|
||
|
||
YAP can also be used to run Prolog files as scripts, at least in
|
||
Unix-like environments. A simple example is shown next:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/local/bin/yap -L --
|
||
#
|
||
# Hello World script file using Yap
|
||
#
|
||
# put a dot because of syntax errors .
|
||
|
||
:- write('Hello World'), nl.
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{#!} characters specify that the script should call the binary
|
||
file Yap. Notice that many systems will require the complete path to the
|
||
Yap binary. The @code{-L} flag indicates that YAP should consult the
|
||
current file when booting and then halt. The remaining arguments are
|
||
then passed to YAP. Note that YAP will skip the first lines if they
|
||
start with @code{#} (the comment sign for Unix's shell). YAP will
|
||
consult the file and execute any commands.
|
||
|
||
A slightly more sophisticated example is:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L --
|
||
#
|
||
# Hello World script file using Yap
|
||
# .
|
||
|
||
:- initialization(main).
|
||
|
||
main :- write('Hello World'), nl.
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{initialization} directive tells Yap to execute the goal main
|
||
after consulting the file. Source code is thus compiled and @code{main}
|
||
executed at the end. The @code{.} is useful while debugging the script
|
||
as a Prolog program: it guarantees that the syntax error will not
|
||
propagate to the Prolog code.
|
||
|
||
Notice that the @code{--} is required so that the shell passes the extra
|
||
arguments to YAP. As an example, consider the following script
|
||
@code{dump_args}:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L --
|
||
#.
|
||
|
||
main( [] ).
|
||
main( [H|T] ) :-
|
||
write( H ), nl,
|
||
main( T ).
|
||
|
||
:- unix( argv(AllArgs) ), main( AllArgs ).
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
If you this run this script with the arguments:
|
||
@example
|
||
./dump_args -s 10000
|
||
@end example
|
||
@noindent
|
||
the script will start an YAP process with stack size @code{10MB}, and
|
||
the list of arguments to the process will be empty.
|
||
|
||
Often one wants to run the script as any other program, and for this it
|
||
is convenient to ignore arguments to YAP. This is possible by using
|
||
@code{L --} as in the next version of @code{dump_args}:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L --
|
||
|
||
main( [] ).
|
||
main( [H|T] ) :-
|
||
write( H ), nl,
|
||
main( T ).
|
||
|
||
:- unix( argv(AllArgs) ), main( AllArgs ).
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{--} indicates the next arguments are not for YAP. Instead,
|
||
they must be sent directly to the @code{argv} built-in. Hence, running
|
||
@example
|
||
./dump_args test
|
||
@end example
|
||
@noindent
|
||
will write @code{test} on the standard output.
|
||
|
||
|
||
@node Syntax, Loading Programs, Run, Top
|
||
@chapter Syntax
|
||
|
||
We will describe the syntax of YAP at two levels. We first will
|
||
describe the syntax for Prolog terms. In a second level we describe
|
||
the @i{tokens} from which Prolog @i{terms} are
|
||
built.
|
||
|
||
@menu
|
||
* Formal Syntax:: Syntax of terms
|
||
* Tokens:: Syntax of Prolog tokens
|
||
@end menu
|
||
|
||
@node Formal Syntax, Tokens, ,Syntax
|
||
@section Syntax of Terms
|
||
@cindex syntax
|
||
|
||
Below, we describe the syntax of YAP terms from the different
|
||
classes of tokens defined above. The formalism used will be @emph{BNF},
|
||
extended where necessary with attributes denoting integer precedence or
|
||
operator type.
|
||
|
||
@example
|
||
|
||
@code{
|
||
term ----> subterm(1200) end_of_term_marker
|
||
|
||
subterm(N) ----> term(M) [M <= N]
|
||
|
||
term(N) ----> op(N, fx) subterm(N-1)
|
||
| op(N, fy) subterm(N)
|
||
| subterm(N-1) op(N, xfx) subterm(N-1)
|
||
| subterm(N-1) op(N, xfy) subterm(N)
|
||
| subterm(N) op(N, yfx) subterm(N-1)
|
||
| subterm(N-1) op(N, xf)
|
||
| subterm(N) op(N, yf)
|
||
|
||
term(0) ----> atom '(' arguments ')'
|
||
| '(' subterm(1200) ')'
|
||
| '@{' subterm(1200) '@}'
|
||
| list
|
||
| string
|
||
| number
|
||
| atom
|
||
| variable
|
||
|
||
arguments ----> subterm(999)
|
||
| subterm(999) ',' arguments
|
||
|
||
list ----> '[]'
|
||
| '[' list_expr ']'
|
||
|
||
list_expr ----> subterm(999)
|
||
| subterm(999) list_tail
|
||
|
||
list_tail ----> ',' list_expr
|
||
| ',..' subterm(999)
|
||
| '|' subterm(999)
|
||
}
|
||
@end example
|
||
|
||
@noindent
|
||
Notes:
|
||
|
||
@itemize @bullet
|
||
|
||
@item
|
||
@i{op(N,T)} denotes an atom which has been previously declared with type
|
||
@i{T} and base precedence @i{N}.
|
||
|
||
@item
|
||
Since ',' is itself a pre-declared operator with type @i{xfy} and
|
||
precedence 1000, is @i{subterm} starts with a '(', @i{op} must be
|
||
followed by a space to avoid ambiguity with the case of a functor
|
||
followed by arguments, e.g.:
|
||
|
||
@example
|
||
@code{ + (a,b) [the same as '+'(','(a,b)) of arity one]}
|
||
@end example
|
||
versus
|
||
@example
|
||
@code{ +(a,b) [the same as '+'(a,b) of arity two]}
|
||
@end example
|
||
|
||
@item
|
||
In the first rule for term(0) no blank space should exist between
|
||
@i{atom} and '('.
|
||
|
||
@item
|
||
@cindex end of term
|
||
Each term to be read by the YAP parser must end with a single
|
||
dot, followed by a blank (in the sense mentioned in the previous
|
||
paragraph). When a name consisting of a single dot could be taken for
|
||
the end of term marker, the ambiguity should be avoided by surrounding the
|
||
dot with single quotes.
|
||
|
||
@end itemize
|
||
|
||
@node Tokens, , Formal Syntax, Syntax
|
||
@section Prolog Tokens
|
||
@cindex token
|
||
|
||
Prolog tokens are grouped into the following categories:
|
||
|
||
@menu
|
||
* Numbers:: Integer and Floating-Point Numbers
|
||
* Strings:: Sequences of Characters
|
||
* Atoms:: Atomic Constants
|
||
* Variables:: Logical Variables
|
||
* Punctuation Tokens:: Tokens that separate other tokens
|
||
* Layout:: Comments and Other Layout Rules
|
||
@end menu
|
||
|
||
@node Numbers, Strings, ,Tokens
|
||
@subsection Numbers
|
||
@cindex number
|
||
|
||
Numbers can be further subdivided into integer and floating-point numbers.
|
||
|
||
@menu
|
||
* Integers:: How Integers are read and represented
|
||
* Floats:: Floating Point Numbers
|
||
@end menu
|
||
|
||
@node Integers, Floats, ,Numbers
|
||
@subsubsection Integers
|
||
@cindex integer
|
||
|
||
Integer numbers
|
||
are described by the following regular expression:
|
||
|
||
@example
|
||
@code{
|
||
<integer> := @{<digit>+<single-quote>|0@{xXo@}@}<alpha_numeric_char>+
|
||
}
|
||
@end example
|
||
@noindent
|
||
where @{...@} stands for optionality, @i{+} optional repetition (one or
|
||
more times), @i{<digit>} denotes one of the characters 0 ... 9, @i{|}
|
||
denotes or, and @i{<single-quote>} denotes the character "'". The digits
|
||
before the @i{<single-quote>} character, when present, form the number
|
||
basis, that can go from 0, 1 and up to 36. Letters from @code{A} to
|
||
@code{Z} are used when the basis is larger than 10.
|
||
|
||
Note that if no basis is specified then base 10 is assumed. Note also
|
||
that the last digit of an integer token can not be immediately followed
|
||
by one of the characters 'e', 'E', or '.'.
|
||
|
||
Following the ISO standard, YAP also accepts directives of the
|
||
form @code{0x} to represent numbers in hexadecimal base and of the form
|
||
@code{0o} to represent numbers in octal base. For usefulness,
|
||
YAP also accepts directives of the form @code{0X} to represent
|
||
numbers in hexadecimal base.
|
||
|
||
Example:
|
||
the following tokens all denote the same integer
|
||
@example
|
||
@code{10 2'1010 3'101 8'12 16'a 36'a 0xa 0o12}
|
||
@end example
|
||
|
||
Numbers of the form @code{0'a} are used to represent character
|
||
constants. So, the following tokens denote the same integer:
|
||
@example
|
||
@code{0'd 100}
|
||
@end example
|
||
|
||
YAP (version @value{VERSION}) supports integers that can fit
|
||
the word size of the machine. This is 32 bits in most current machines,
|
||
but 64 in some others, such as the Alpha running Linux or Digital
|
||
Unix. The scanner will read larger or smaller integers erroneously.
|
||
|
||
@node Floats, , Integers,Numbers
|
||
@subsubsection Floating-point Numbers
|
||
@cindex floating-point number
|
||
|
||
Floating-point numbers are described by:
|
||
|
||
@example
|
||
@code{
|
||
<float> := <digit>+@{<dot><digit>+@}
|
||
<exponent-marker>@{<sign>@}<digit>+
|
||
|<digit>+<dot><digit>+
|
||
@{<exponent-marker>@{<sign>@}<digit>+@}
|
||
}
|
||
@end example
|
||
|
||
@noindent
|
||
where @i{<dot>} denotes the decimal-point character '.',
|
||
@i{<exponent-marker>} denotes one of 'e' or 'E', and @i{<sign>} denotes
|
||
one of '+' or '-'.
|
||
|
||
Examples:
|
||
@example
|
||
@code{10.0 10e3 10e-3 3.1415e+3}
|
||
@end example
|
||
|
||
Floating-point numbers are represented as a double in the target
|
||
machine. This is usually a 64-bit number.
|
||
|
||
@node Strings, Atoms, Numbers,Tokens
|
||
@subsection Character Strings
|
||
@cindex string
|
||
|
||
Strings are described by the following rules:
|
||
@example
|
||
string --> '"' string_quoted_characters '"'
|
||
|
||
string_quoted_characters --> '"' '"' string_quoted_characters
|
||
string_quoted_characters --> '\'
|
||
escape_sequence string_quoted_characters
|
||
string_quoted_characters -->
|
||
string_character string_quoted_characters
|
||
|
||
escape_sequence --> 'a' | 'b' | 'r' | 'f' | 't' | 'n' | 'v'
|
||
escape_sequence --> '\' | '"' | ''' | '`'
|
||
escape_sequence --> at_most_3_octal_digit_seq_char '\'
|
||
escape_sequence --> 'x' at_most_2_hexa_digit_seq_char '\'
|
||
@end example
|
||
where @code{string_character} in any character except the double quote
|
||
and escape characters.
|
||
|
||
Examples:
|
||
@example
|
||
@code{"" "a string" "a double-quote:""" }
|
||
@end example
|
||
|
||
The first string is an empty string, the last string shows the use of
|
||
double-quoting. The implementation of YAP represents strings as
|
||
lists of integers. Since Yap4.3.0 there is no static limit on string
|
||
size.
|
||
|
||
Escape sequences can be used to include the non-printable characters
|
||
@code{a} (alert), @code{b} (backspace), @code{r} (carriage return),
|
||
@code{f} (form feed), @code{t} (horizontal tabulation), @code{n} (new
|
||
line), and @code{v} (vertical tabulation). Escape sequences also be
|
||
include the meta-characters @code{\}, @code{"}, @code{'}, and
|
||
@code{`}. Last, one can use escape sequences to include the characters
|
||
either as an octal or hexadecimal number.
|
||
|
||
The next examples demonstrates the use of escape sequences in YAP:
|
||
|
||
@example
|
||
@code{"\x0c\" "\01\" "\f" "\\" }
|
||
@end example
|
||
|
||
The first three examples return a list including only character 12 (form
|
||
feed). The last example escapes the escape character.
|
||
|
||
Escape sequences were not available in C-Prolog and in original
|
||
versions of YAP up to 4.2.0. Escape sequences can be disable by using:
|
||
@example
|
||
@code{:- yap_flag(character_escapes,off).}
|
||
@end example
|
||
|
||
|
||
@node Atoms, Variables, Strings, Tokens
|
||
@subsection Atoms
|
||
@cindex atom
|
||
|
||
Atoms are defined by one of the following rules:
|
||
@example
|
||
atom --> solo-character
|
||
atom --> lower-case-letter name-character*
|
||
atom --> symbol-character+
|
||
atom --> single-quote single-quote
|
||
atom --> ''' atom_quoted_characters '''
|
||
|
||
|
||
atom_quoted_characters --> ''' ''' atom_quoted_characters
|
||
atom_quoted_characters --> '\' atom_sequence string_quoted_characters
|
||
atom_quoted_characters --> character string_quoted_characters
|
||
|
||
@end example
|
||
|
||
where:
|
||
@example
|
||
<solo-character> denotes one of: ! ;
|
||
<symbol-character> denotes one of: # & * + - . / : <
|
||
= > ? @@ \ ^ ` ~
|
||
<lower-case-letter> denotes one of: a...z
|
||
<name-character> denotes one of: _ a...z A...Z 0....9
|
||
<single-quote> denotes: '
|
||
@end example
|
||
|
||
and @code{string_character} denotes any character except the double quote
|
||
and escape characters. Note that escape sequences in strings and atoms
|
||
follow the same rules.
|
||
|
||
Examples:
|
||
@example
|
||
@code{a a12x '$a' ! => '1 2'}
|
||
@end example
|
||
|
||
|
||
Version @code{4.2.0} of YAP removed the previous limit of 256
|
||
characters on an atom. Size of an atom is now only limited by the space
|
||
available in the system.
|
||
|
||
@node Variables, Punctuation Tokens, Atoms, Tokens
|
||
@subsection Variables
|
||
@cindex variable
|
||
|
||
Variables are described by:
|
||
@example
|
||
<variable-starter><variable-character>+
|
||
@end example
|
||
where
|
||
@example
|
||
<variable-starter> denotes one of: _ A...Z
|
||
<variable-character> denotes one of: _ a...z A...Z
|
||
@end example
|
||
|
||
@cindex anonymous variable
|
||
If a variable is referred only once in a term, it needs not to be named
|
||
and one can use the character @code{_} to represent the variable. These
|
||
variables are known as anonymous variables. Note that different
|
||
occurrences of @code{_} on the same term represent @emph{different}
|
||
anonymous variables.
|
||
|
||
@node Punctuation Tokens, Layout, Variables, Tokens
|
||
@subsection Punctuation Tokens
|
||
@cindex punctuation token
|
||
|
||
Punctuation tokens consist of one of the following characters:
|
||
@example
|
||
@center ( ) , [ ] @{ @} |
|
||
@end example
|
||
|
||
These characters are used to group terms.
|
||
|
||
@node Layout, ,Punctuation Tokens, Tokens
|
||
@subsection Layout
|
||
@cindex comment
|
||
Any characters with ASCII code less than or equal to 32 appearing before
|
||
a token are ignored.
|
||
|
||
All the text appearing in a line after the character @i{%} is taken to
|
||
be a comment and ignored (including @i{%}). Comments can also be
|
||
inserted by using the sequence @code{/*} to start the comment and
|
||
@code{*/} to finish it. In the presence of any sequence of comments or
|
||
layout characters, the YAP parser behaves as if it had found a
|
||
single blank character. The end of a file also counts as a blank
|
||
character for this purpose.
|
||
|
||
@node Loading Programs, Modules, Syntax, Top
|
||
@chapter Loading Programs
|
||
|
||
@menu
|
||
|
||
Loading Programs
|
||
* Compiling:: Program Loading and Updating
|
||
* Setting the Compiler:: Changing the compiler's parameters
|
||
* Saving:: Saving and Restoring Programs
|
||
|
||
@end menu
|
||
|
||
|
||
@node Compiling, Setting the Compiler, , Loading Programs
|
||
@section Program loading and updating
|
||
|
||
@table @code
|
||
|
||
@item consult(@var{+F})
|
||
@findex consult/1
|
||
@snindex consult/1
|
||
@cyindex consult/1
|
||
Adds the clauses written in file @var{F} or in the list of files @var{F}
|
||
to the program.
|
||
|
||
In YAP @code{consult/1} does not remove previous clauses for
|
||
the procedures defined in @var{F}. Moreover, note that all code in YAP
|
||
is compiled.
|
||
|
||
@item reconsult(@var{+F})
|
||
@findex reconsult/1
|
||
@snindex reconsult/1
|
||
@cyindex reconsult/1
|
||
Updates the program replacing the
|
||
previous definitions for the predicates defined in @var{F}.
|
||
|
||
|
||
@item [@var{+F}]
|
||
@findex []/1
|
||
@saindex []/1
|
||
@cyindex []/1
|
||
The same as @code{consult(F)}.
|
||
|
||
@item [-@var{+F}]
|
||
@findex [-]/1
|
||
@saindex [-]/1
|
||
@cyindex [-]/1
|
||
The same as @code{reconsult(F)}
|
||
|
||
Example:
|
||
|
||
@example
|
||
?- [file1, -file2, -file3, file4].
|
||
@end example
|
||
@noindent
|
||
will consult @code{file1} @code{file4} and reconsult @code{file2} and
|
||
@code{file3}.
|
||
|
||
@item compile(@var{+F})
|
||
@findex compile/1
|
||
@syindex compile/1
|
||
@cnindex compile/1
|
||
@noindent
|
||
In YAP, the same as @code{reconsult/1}.
|
||
|
||
@item ensure_loaded(@var{+F}) [ISO]
|
||
@findex ensure_loaded/1
|
||
@syindex compile/1
|
||
@cnindex compile/1
|
||
When the files specified by @var{F} are module files,
|
||
@code{ensure_loaded/1} loads them if they have note been previously
|
||
loaded, otherwise advertises the user about the existing name clashes
|
||
and prompts about importing or not those predicates. Predicates which
|
||
are not public remain invisible.
|
||
|
||
When the files are not module files, @code{ensure_loaded/1} loads them
|
||
if they have not been loaded before, does nothing otherwise.
|
||
|
||
@var{F} must be a list containing the names of the files to load.
|
||
|
||
@item include(@var{+F}) [ISO]
|
||
@findex include/1 (directive)
|
||
@snindex compile/1 (directive)
|
||
@cnindex compile/1 (directive)
|
||
The @code{include} directive includes the text files or sequence of text
|
||
files specified by @var{F} into the file being currently consulted.
|
||
|
||
@end table
|
||
|
||
@node Setting the Compiler, Saving, Compiling, Loading Programs
|
||
@section Changing the Compiler's Behavior
|
||
|
||
This section presents a set of built-ins predicates designed to set the
|
||
environment for the compiler.
|
||
|
||
@table @code
|
||
|
||
@item source_mode(-@var{O},+@var{N})
|
||
@findex source_mode/2
|
||
@snindex source_mode/2
|
||
@cnindex source_mode/2
|
||
The state of source mode can either be on or off. When the source mode
|
||
is on, all clauses are kept both as compiled code and in a "hidden"
|
||
database. @var{O} is unified with the previous state and the mode is set
|
||
according to @var{N}.
|
||
|
||
@item source
|
||
@findex source/0
|
||
@snindex source/0
|
||
@cnindex source/0
|
||
After executing this goal, YAP keeps information on the source
|
||
of the predicates that will be consulted. This enables the use of
|
||
@code{listing/0}, @code{listing/1} and @code{clause/2} for those
|
||
clauses.
|
||
|
||
The same as @code{source_mode(_,on)} or as declaring all newly defined
|
||
static procedures as @code{public}.
|
||
|
||
@item no_source
|
||
@findex no_source/0
|
||
@snindex no_source/0
|
||
@cnindex no_source/0
|
||
The opposite to @code{source}.
|
||
|
||
The same as @code{source_mode(_,off)}.
|
||
|
||
@item compile_expressions
|
||
@findex compile_expressions/0
|
||
@snindex compile_expressions/0
|
||
@cnindex compile_expressions/0
|
||
After a call to this predicate, arithmetical expressions will be compiled.
|
||
(see example below). This is the default behavior.
|
||
|
||
@item do_not_compile_expressions
|
||
@findex do_not_compile_expressions/0
|
||
@snindex do_not_compile_expressions/0
|
||
@cnindex do_not_compile_expressions/0
|
||
After a call to this predicate, arithmetical expressions will not be compiled.
|
||
@example
|
||
?- source, do_not_compile_expressions.
|
||
yes
|
||
?- [user].
|
||
| p(X) :- X is 2 * (3 + 8).
|
||
| :- end_of_file.
|
||
?- compile_expressions.
|
||
yes
|
||
?- [user].
|
||
| q(X) :- X is 2 * (3 + 8).
|
||
| :- end_of_file.
|
||
:- listing.
|
||
|
||
p(A):-
|
||
A is 2 * (3 + 8).
|
||
|
||
q(A):-
|
||
A is 22.
|
||
@end example
|
||
|
||
@item hide(+@var{Atom})
|
||
@findex hide/1
|
||
@snindex hide/1
|
||
@cnindex hide/1
|
||
Make atom @var{Atom} invisible.
|
||
|
||
@item unhide(+@var{Atom})
|
||
@findex unhide/1
|
||
@snindex unhide/1
|
||
@cnindex unhide/1
|
||
Make hidden atom @var{Atom} visible.
|
||
|
||
|
||
@item hide_predicate(+@var{Pred})
|
||
@findex hide_predicate/1
|
||
@snindex hide_predicate/1
|
||
@cnindex hide_predicate/1
|
||
Make predicate @var{Pred} invisible to @code{current_predicate/2},
|
||
@code{listing}, and friends.
|
||
|
||
@item expand_exprs(-@var{O},+@var{N})
|
||
@findex expand_exprs/2
|
||
@snindex expand_exprs/2
|
||
@cyindex expand_exprs/2
|
||
Puts YAP in state @var{N} (@code{on} or @code{off}) and unify
|
||
@var{O} with the previous state, where @var{On} is equivalent to
|
||
@code{compile_expressions} and @code{off} is equivalent to
|
||
@code{do_not_compile_expressions}. This predicate was kept to maintain
|
||
compatibility with C-Prolog.
|
||
|
||
@item path(-@var{D})
|
||
@findex path/1
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Unifies @var{D} with the current directory search-path of YAP.
|
||
Note that this search-path is only used by YAP to find the
|
||
files for @code{consult/1}, @code{reconsult/1} and @code{restore/1} and
|
||
should not be taken for the system search path.
|
||
|
||
@item add_to_path(+@var{D})
|
||
@findex add_to_path/1
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Adds @var{D} to the end of YAP's directory search path.
|
||
|
||
@item add_to_path(+@var{D},+@var{N})
|
||
@findex add_to_path/2
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Inserts @var{D} in the position, of the directory search path of
|
||
YAP, specified by @var{N}. @var{N} must be either of
|
||
@code{first} or @code{last}.
|
||
|
||
@item remove_from_path(+@var{D})
|
||
@findex remove_from_path/1
|
||
@snindex remove_from_path/1
|
||
@cnindex remove_from_path/1
|
||
Remove @var{D} from YAP's directory search path.
|
||
|
||
@item style_check(+@var{X})
|
||
@findex style_check/1
|
||
@snindex style_check/1
|
||
@cnindex style_check/1
|
||
Turns on style checking according to the attribute specified by @var{X},
|
||
which must be one of the following:
|
||
@table @code
|
||
@item single_var
|
||
Checks single occurrences of named variables in a clause.
|
||
@item discontiguous
|
||
Checks non-contiguous clauses for the same predicate in a file.
|
||
@item multiple
|
||
Checks the presence of clauses for the same predicate in more than one
|
||
file when the predicate has not been declared as @code{multifile}
|
||
@item all
|
||
Performs style checking for all the cases mentioned above.
|
||
@end table
|
||
By default, style checking is disabled in YAP unless we are in
|
||
@code{sicstus} or @code{iso} language mode.
|
||
|
||
The @code{style_check/1} built-in is now deprecated. Please use the
|
||
@code{set_prolog_flag/1} instead.
|
||
|
||
@item no_style_check(+@var{X})
|
||
@findex no_style_check/1
|
||
@snindex style_check/1
|
||
@cnindex style_check/1
|
||
Turns off style checking according to the attribute specified by
|
||
@var{X}, which has the same meaning as in @code{style_check/1}.
|
||
|
||
The @code{no_style_check/1} built-in is now deprecated. Please use the
|
||
@code{set_prolog_flag/1} instead.
|
||
|
||
@item multifile @var{P} [ISO]
|
||
@findex multifile/1 (directive)
|
||
@syindex multifile/1 (directive)
|
||
@cnindex multifile/1 (directive)
|
||
Instructs the compiler about the declaration of a predicate @var{P} in
|
||
more than one file. It must appear in the first of the loaded files
|
||
where the predicate is declared, and before declaration of any of its
|
||
clauses.
|
||
|
||
Multifile declarations affect @code{reconsult/1} and @code{compile/1}:
|
||
when a multifile predicate is reconsulted, only the clauses from the
|
||
same file are removed.
|
||
|
||
Since Yap4.3.0 multifile procedures can be static or dynamic.
|
||
|
||
@item discontiguous(+@var{G}) [ISO]
|
||
@findex discontiguous/1 (directive)
|
||
@syindex discontiguous/1 (directive)
|
||
@cnindex discontiguous/1 (directive)
|
||
|
||
Declare that the arguments are discontiguous procedures, that is,
|
||
clauses for discontigous procedures may be separated by clauses from
|
||
other procedures.
|
||
|
||
@item initialization(+@var{G}) [ISO]
|
||
@findex initialization/1 (directive)
|
||
@snindex initialization/1 (directive)
|
||
@cnindex initialization/1 (directive)
|
||
The compiler will execute goals @var{G} after consulting the current
|
||
file.
|
||
|
||
@item library_directory(+@var{D})
|
||
@findex library_directory/1
|
||
@snindex library_directory/1
|
||
@cnindex library_directory/1
|
||
Succeeds when @var{D} is a current library directory name. Library
|
||
directories are the places where files specified in the form
|
||
@code{library(@var{File})} are searched by the predicates
|
||
@code{consult/1}, @code{reconsult/1}, @code{use_module/1} or
|
||
@code{ensure_loaded/1}.
|
||
|
||
@item file_search_path(+@var{NAME},-@var{DIRECTORY})
|
||
@findex file_search_path/2
|
||
@syindex file_search_path/2
|
||
@cnindex file_search_path/2
|
||
Allows writing file names as compound terms. The @var{NAME} and
|
||
@var{DIRECTORY} must be atoms. The predicate may generate multiple
|
||
solutions. The predicate is originally defined as follows:
|
||
|
||
@example
|
||
file_search_path(library,A) :-
|
||
library_directory(A).
|
||
file_search_path(system,A) :-
|
||
prolog_flag(host_type,A).
|
||
@end example
|
||
|
||
Thus, [library(A)] will search for a file using
|
||
@var{library_directory}/1 to obtain the prefix.
|
||
|
||
@item library_directory(+@var{D})
|
||
@findex library_directory/1
|
||
@snindex library_directory/1
|
||
@cnindex library_directory/1
|
||
Succeeds when @var{D} is a current library directory name. Library
|
||
directories are the places where files specified in the form
|
||
@code{library(@var{File})} are searched by the predicates
|
||
@code{consult/1}, @code{reconsult/1}, @code{use_module/1} or
|
||
@code{ensure_loaded/1}.
|
||
|
||
@item prolog_file_name(+@var{Name},-@var{FullPath})
|
||
@findex prolog_file_name/2
|
||
@syindex prolog_file_name/1
|
||
@cnindex prolog_file_name/2
|
||
Unify @var{FullPath} with the absolute path YAP would use to consult
|
||
file @var{Name}.
|
||
|
||
@item public @var{P} [ISO]
|
||
@findex public/1 (directive)
|
||
@snindex public/1 (directive)
|
||
@cnindex public/1 (directive)
|
||
Instructs the compiler that the source of a predicate of a list of
|
||
predicates @var{P} must be kept. This source is then accessible through
|
||
the @code{clause/2} procedure and through the @code{listing} family of
|
||
built-ins.
|
||
|
||
Note that all dynamic procedures are public. The @code{source} directive
|
||
defines all new or redefined predicates to be public.
|
||
|
||
Since Yap4.3.0 multifile procedures can be static or dynamic.
|
||
|
||
@end table
|
||
|
||
@node Saving, , Setting the Compiler, Loading Programs
|
||
@section Saving and Loading Prolog States
|
||
|
||
@table @code
|
||
@item save(+@var{F})
|
||
@findex save/1
|
||
@snindex save/1
|
||
@cyindex save/1
|
||
Saves an image of the current state of YAP in file @var{F}. From
|
||
@strong{Yap4.1.3} onwards, YAP saved states are executable
|
||
files in the Unix ports.
|
||
|
||
@item save(+@var{F},-@var{OUT})
|
||
@findex save/2
|
||
@snindex save/2
|
||
@cnindex save/2
|
||
Saves an image of the current state of YAP in file @var{F}. From
|
||
@strong{Yap4.1.3} onwards, YAP saved states are executable
|
||
files in the Unix ports.
|
||
|
||
Unify @var{OUT} with 1 when saving the file and @var{OUT} with 0 when
|
||
restoring the saved state.
|
||
|
||
@item save_program(+@var{F})
|
||
@findex save_program/1
|
||
@syindex save_program/1
|
||
@cnindex save_program/1
|
||
Saves an image of the current state of the YAP database in file
|
||
@var{F}.
|
||
|
||
@item save_program(+@var{F}, :@var{G})
|
||
@findex save_program/2
|
||
@syindex save_program/2
|
||
@cnindex save_program/2
|
||
Saves an image of the current state of the YAP database in file
|
||
@var{F}, and guarantee that execution of the restored code will start by
|
||
trying goal @var{G}.
|
||
|
||
@item restore(+@var{F})
|
||
@findex restore/1
|
||
@syindex restore/1
|
||
@cnindex restore/1
|
||
Restores a previously saved state of YAP from file @var{F}.
|
||
|
||
YAP always tries to find saved states from the current directory
|
||
first. If it cannot it will use the environment variable YAPLIBDIR, if
|
||
defined, or search the default library directory.
|
||
@end table
|
||
|
||
|
||
@node Modules, Builtins, Loading Programs, Top
|
||
@chapter The Module System
|
||
|
||
Module systems are quite important for the development of large
|
||
applications. YAP implements a module system compatible with the Quintus
|
||
Prolog module system.
|
||
|
||
The YAP module system is predicate-based. This means a module consists
|
||
of a set of predicates (or procedures), such that some predicates are
|
||
public and the others are local to a module. Atoms and terms in general
|
||
are global to the system. Moreover, the module system is flat, meaning
|
||
that we do not support an hierarchy of modules. Modules can
|
||
automatically import other modules, though. For compatibility with other
|
||
module systems the YAP module system is non-strict, meaning both that
|
||
there is both a way to access predicates private to a module and that is
|
||
possible to declare predicates for a module from some other module.
|
||
|
||
YAP allows one to ignore the module system if one does not want to use
|
||
it. Last note that using the module system does not introduce any
|
||
significant overheads: only meta-calls that cross module boundaries are
|
||
slowed down by the presence of modules.
|
||
|
||
@menu
|
||
|
||
* Module Concepts:: The Key Ideas in Modules
|
||
* Defining Modules:: How To Define a New Module
|
||
* Using Modules:: How to Use a Module
|
||
* Meta-Predicates in Modules:: How to Handle New Meta-Predicates
|
||
|
||
@end menu
|
||
|
||
@node Module Concepts, Defining Modules, , Modules
|
||
@section Module Concepts
|
||
|
||
The YAP module system applies to predicates. All predicates belong to a
|
||
module. System predicates belong to the module @code{primitives}, and by
|
||
default new predicates belong to the module @code{user}. Predicates from
|
||
the module @code{primitives} are automatically visible to every module.
|
||
|
||
Every predicate must belong to a module. This module is called its
|
||
@emph{source module}.
|
||
|
||
By default, the source module for a clause occurring in a source file
|
||
with a module declaration is the declared module. For goals typed in
|
||
a source file without module declarations, their module is the module
|
||
the file is being loaded into. If no module declarations exist, this is
|
||
the current @emph{type-in module}. The default type-in module is
|
||
@code{user}, but one can set the current module by using the built-in
|
||
@code{module/1}.
|
||
|
||
Note that in this module system one can explicitly specify the source
|
||
mode for a clause by prefixing a clause with its module, say:
|
||
@example
|
||
user:(a :- b).
|
||
@end example
|
||
@noindent
|
||
In fact, to specify the source module for a clause it is sufficient to
|
||
specify the source mode for the clause's head:
|
||
@example
|
||
user:a :- b.
|
||
@end example
|
||
@noindent
|
||
|
||
The rules for goals are similar. If a goal appears in a text file with a
|
||
module declaration, the goal's source module is the declared
|
||
module. Otherwise, it is the module the file is being loaded into or the
|
||
type-in module.
|
||
|
||
One can override this rule by prefixing a goal with the module it is
|
||
supposed to be executed into, say:
|
||
@example
|
||
nasa:launch(apollo,13).
|
||
@end example
|
||
will execute the goal @code{launch(apollo,13)} as if the current source
|
||
module was @code{nasa}.
|
||
|
||
Note that this rule breaks encapsulation and should be used with care.
|
||
|
||
@node Defining Modules, Using Modules, Module Concepts, Modules
|
||
@section Defining a New Module
|
||
|
||
A new module is defined by a @code{module} declaration:
|
||
|
||
@table @code
|
||
|
||
@item module(+@var{M},+@var{L})
|
||
@findex module/2 (directive)
|
||
@syindex module/2 (directive)
|
||
@cnindex module/2 (directive)
|
||
This predicate defines the file where it appears as a module file; it
|
||
must be the first declaration in the file.
|
||
@var{M} must be an atom specifying the module name; @var{L} must be a list
|
||
containing the module's public predicates specification, in the form
|
||
@code{[predicate_name/arity,...]}.
|
||
|
||
The public predicates of a module file can be made accessible by other
|
||
files through the predicates @code{consult/1}, @code{reconsult/1},
|
||
@code{ensure_loaded/1} or @code{use_module/2}. The non-public predicates
|
||
of a module file are not visible by other files; they can, however, be
|
||
accessed if the module name is prefixed to the file name through the
|
||
@code{:/2} operator.
|
||
|
||
@end table
|
||
|
||
The built-in @code{module/1} sets the current source module:
|
||
@table @code
|
||
|
||
@item module(+@var{M},+@var{L}, +@var{Options})
|
||
@findex module/3 (directive)
|
||
@syindex module/3 (directive)
|
||
@cnindex module/3 (directive)
|
||
Similar to @code{module/2}, this predicate defines the file where it
|
||
appears as a module file; it must be the first declaration in the file.
|
||
@var{M} must be an atom specifying the module name; @var{L} must be a
|
||
list containing the module's public predicates specification, in the
|
||
form @code{[predicate_name/arity,...]}.
|
||
|
||
The last argument @var{Options} must be a list of options, which can be:
|
||
|
||
@table @code
|
||
@item filename
|
||
the filename for a module to import into the current module.
|
||
|
||
@item library(file)
|
||
a library file to import into the current module.
|
||
|
||
@item hide(@var{Opt})
|
||
if @var{Opt} is @code{false}, keep source code for current module, if
|
||
@code{true}, disable.
|
||
@end table
|
||
|
||
@item module(+@var{M})
|
||
@findex module/1
|
||
@syindex module/1
|
||
@cnindex module/1
|
||
Defines @var{M} to be the current working or type-in module. All files
|
||
which are not binded to a module are assumed to belong to the working
|
||
module (also referred to as type-in module). To compile a non-module
|
||
file into a module which is not the working one, prefix the file name
|
||
with the module name, in the form @code{@var{Module}:@var{File}}, when
|
||
loading the file.
|
||
|
||
@end table
|
||
|
||
@node Using Modules, Meta-Predicates in Modules, Defining Modules, Modules
|
||
@section Using Modules
|
||
|
||
By default, all procedures to consult a file will load the modules
|
||
defined therein. The two following declarations allow one to import a
|
||
module explicitly. They differ on whether one imports all predicate
|
||
declared in the module or not.
|
||
|
||
@table @code
|
||
|
||
@item use_module(+@var{F})
|
||
@findex use_module/1
|
||
@syindex use_module/1
|
||
@cnindex use_module/1
|
||
Loads the files specified by @var{F}, importing all their public
|
||
predicates. Predicate name clashes are resolved by asking the user about
|
||
importing or not the predicate. A warning is displayed when @var{F} is
|
||
not a module file.
|
||
|
||
@item use_module(+@var{F},+@var{L})
|
||
@findex use_module/2
|
||
@syindex use_module/2
|
||
@cnindex use_module/2
|
||
Loads the files specified by @var{F}, importing the predicates specified
|
||
in the list @var{L}. Predicate name clashes are resolved by asking the
|
||
user about importing or not the predicate. A warning is displayed when
|
||
@var{F} is not a module file.
|
||
|
||
@item use_module(?@var{M},?@var{F},+@var{L})
|
||
@findex use_module/3
|
||
@syindex use_module/3
|
||
@cnindex use_module/3
|
||
If module @var{M} has been defined, import the procedures in @var{L} to
|
||
the current module. Otherwise, load the files specified by @var{F},
|
||
importing the predicates specified in the list @var{L}.
|
||
@end table
|
||
|
||
@node Meta-Predicates in Modules, , Using Modules, Modules
|
||
@section Meta-Predicates in Modules
|
||
|
||
The module system must know whether predicates operate on goals or
|
||
clauses. Otherwise, such predicates would call a goal in the module they
|
||
were defined, instead of calling it in the module they are currently
|
||
executing. So, for instance:
|
||
@example
|
||
:- module(example,[a/1]).
|
||
|
||
...
|
||
|
||
a(G) :- call(G)
|
||
|
||
...
|
||
|
||
@end example
|
||
The expected behavior for this procedure is to execute goal @var{G}
|
||
within the current module, that is, within @code{example}.
|
||
On the other hand, when executing @code{call/1} the system only knows
|
||
where @code{call/1} was defined, that is, it only knows of
|
||
@code{primitives}. A similar problem arises for @code{assert/1} and
|
||
friends.
|
||
|
||
The @code{meta_predicate/1} declaration informs the system that some
|
||
arguments of a procedure are goals, clauses or clauses heads, and that
|
||
these arguments must be expanded to receive the current source module:
|
||
|
||
@table @code
|
||
|
||
@item meta_predicate @var{G1},....,@var{Gn}
|
||
@findex meta_predicate/1 (directive)
|
||
@syindex meta_predicate/1 (directive)
|
||
@cnindex meta_predicate/1 (directive)
|
||
Each @var{Gi} is a mode specification. For example, a declaration for
|
||
@code{call/1} and @code{setof/3} would be of the form:
|
||
|
||
@example
|
||
:- meta_predicate call(:), setof(?,:,?).
|
||
@end example
|
||
|
||
If the argument is @code{:} or an integer, the argument is a call and
|
||
must be expanded. Otherwise, the argument should not be expanded. Note
|
||
that the system already includes declarations for all built-ins.
|
||
|
||
@end table
|
||
|
||
In the previous example, the only argument to @code{call/1} must be
|
||
expanded, resulting in the following code:
|
||
|
||
@example
|
||
:- module(example,[a/1]).
|
||
|
||
...
|
||
|
||
a(G) :- call(example:G)
|
||
|
||
...
|
||
|
||
@end example
|
||
|
||
@node Builtins, Library, Modules, Top
|
||
|
||
@chapter Built-In Predicates
|
||
|
||
@menu
|
||
|
||
Builtins, Debugging, Syntax, Top
|
||
* Control:: Controlling the Execution of Prolog Programs
|
||
* Undefined Procedures:: Handling calls to Undefined Procedures
|
||
* Testing Terms:: Predicates on Terms
|
||
* Comparing Terms:: Comparison of Terms
|
||
* Arithmetic:: Arithmetic in Yap
|
||
* I/O:: Input/Output with Yap
|
||
* Database:: Modifying Prolog's Database
|
||
* Sets:: Finding All Possible Solutions
|
||
* Grammars:: Grammar Rules
|
||
* Preds:: Predicate Information
|
||
* OS:: Access to Operating System Functionality
|
||
* Term Modification:: Updating Prolog Terms
|
||
* Profiling:: Profiling Prolog Execution
|
||
* Call Counting:: Limiting the Maximum Number of Reductions
|
||
* Arrays:: Supporting Global and Local Arrays
|
||
* Preds:: Information on Predicates
|
||
* Misc:: Miscellaneous Predicates
|
||
|
||
@end menu
|
||
|
||
@node Control, Undefined Procedures, , Top
|
||
@section Control Predicates
|
||
|
||
|
||
This chapter describes the predicates for controlling the execution of
|
||
Prolog programs.
|
||
|
||
In the description of the arguments of functors the following notation
|
||
will be used:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a preceding plus sign will denote an argument as an "input argument" -
|
||
it cannot be a free variable at the time of the call;
|
||
@item
|
||
a preceding minus sign will denote an "output argument";
|
||
@item
|
||
an argument with no preceding symbol can be used in both ways.
|
||
@end itemize
|
||
|
||
|
||
@table @code
|
||
|
||
@item +@var{P}, +@var{Q} [ISO]
|
||
@findex ,/2
|
||
@syindex ,/2
|
||
@cyindex ,/2
|
||
Conjunction of goals (and).
|
||
|
||
@noindent
|
||
Example:
|
||
@example
|
||
p(X) :- q(X), r(X).
|
||
@end example
|
||
|
||
@noindent
|
||
should be read as "p(@var{X}) if q(@var{X}) and r(@var{X})".
|
||
|
||
@item +@var{P} ; +@var{Q} [ISO]
|
||
@findex ;/2
|
||
@syindex ;/2
|
||
@cyindex ;/2
|
||
Disjunction of goals (or).
|
||
|
||
@noindent
|
||
Example:
|
||
@example
|
||
p(X) :- q(X); r(X).
|
||
@end example
|
||
@noindent
|
||
should be read as "p(@var{X}) if q(@var{X}) or r(@var{X})".
|
||
|
||
@item true [ISO]
|
||
@findex true/0
|
||
@syindex true/0
|
||
@cyindex true/0
|
||
Succeeds once.
|
||
|
||
@item fail [ISO]
|
||
@findex fail/0
|
||
@syindex fail/0
|
||
@cyindex fail/0
|
||
Fails always.
|
||
|
||
@item false
|
||
@findex false/0
|
||
@syindex false/0
|
||
@cnindex false/0
|
||
The same as fail
|
||
|
||
@item ! [ISO]
|
||
@findex !/0
|
||
@syindex !/0
|
||
@cyindex !/0
|
||
Read as "cut". Cuts any choices taken in the current procedure.
|
||
When first found "cut" succeeds as a goal, but if backtracking should
|
||
later return to it, the parent goal (the one which matches the head of
|
||
the clause containing the "cut", causing the clause activation) will
|
||
fail. This is an extra-logical predicate and cannot be explained in
|
||
terms of the declarative semantics of Prolog.
|
||
|
||
example:
|
||
|
||
@example
|
||
member(X,[X|_]).
|
||
member(X,[_|L]) :- member(X,L).
|
||
@end example
|
||
|
||
@noindent
|
||
With the above definition
|
||
|
||
@example
|
||
?- member(X,[1,2,3]).
|
||
@end example
|
||
|
||
@noindent
|
||
will return each element of the list by backtracking. With the following
|
||
definition:
|
||
|
||
@example
|
||
member(X,[X|_]) :- !.
|
||
member(X,[_|L]) :- member(X,L).
|
||
@end example
|
||
|
||
@noindent
|
||
the same query would return only the first element of the
|
||
list, since backtracking could not "pass through" the cut.
|
||
|
||
@item \+ +@var{P} [ISO]
|
||
@findex \+/1
|
||
@syindex \+/1
|
||
@cyindex \+/1
|
||
Goal @var{P} is not provable. The execution of this predicate fails if
|
||
and only if the goal @var{P} finitely succeeds. It is not a true logical
|
||
negation, which is impossible in standard Prolog, but
|
||
"negation-by-failure".
|
||
|
||
@noindent
|
||
This predicate might be defined as:
|
||
@example
|
||
\+(P) :- P, !, fail.
|
||
\+(_).
|
||
@end example
|
||
@noindent
|
||
if @var{P} did not include "cuts".
|
||
|
||
@item not +@var{P}
|
||
@findex not/1
|
||
@snindex not/1
|
||
@cyindex not/1
|
||
Goal @var{P} is not provable. The same as @code{'\+ @var{P}'}.
|
||
|
||
This predicate is kept for compatibility with C-Prolog and previous
|
||
versions of YAP. Uses of @code{not/1} should be replace by
|
||
@code{(\+)/1}, as YAP does not implement true negation.
|
||
|
||
@item +@var{P} -> +@var{Q} [ISO]
|
||
@findex ->/2
|
||
@syindex ->/2
|
||
@cnindex ->/2
|
||
Read as "if-then-else" or "commit". This operator is similar to the
|
||
conditional operator of imperative languages and can be used alone or
|
||
with an else part as follows:
|
||
|
||
@table @code
|
||
@item +P -> +Q
|
||
"if P then Q".
|
||
@item +P -> +Q; +R
|
||
"if P then Q else R".
|
||
@end table
|
||
|
||
@noindent
|
||
These two predicates could be defined respectively in Prolog as:
|
||
@example
|
||
(P -> Q) :- P, !, Q.
|
||
@end example
|
||
@noindent
|
||
and
|
||
@example
|
||
(P -> Q; R) :- P, !, Q.
|
||
(P -> Q; R) :- R.
|
||
@end example
|
||
@noindent
|
||
if there were no "cuts" in @var{P}, @var{Q} and @var{R}.
|
||
|
||
Note that the commit operator works by "cutting" any alternative
|
||
solutions of @var{P}.
|
||
|
||
Note also that you can use chains of commit operators like:
|
||
@example
|
||
P -> Q ; R -> S ; T.
|
||
@end example
|
||
@noindent
|
||
Note that @code{(->)/2} does not affect the scope of cuts in its
|
||
arguments.
|
||
|
||
@item repeat [ISO]
|
||
@findex repeat/0
|
||
@syindex repeat/0
|
||
@cyindex repeat/0
|
||
Succeeds repeatedly.
|
||
|
||
In the next example, @code{repeat} is used as an efficient way to implement
|
||
a loop. The next example reads all terms in a file:
|
||
|
||
@example
|
||
a :- repeat, read(X), write(X), nl, X=end_of_file, !.
|
||
@end example
|
||
@noindent
|
||
the loop is effectively terminated by the cut-goal, when the test-goal
|
||
@code{X=end} succeeds. While the test fails, the goals @code{read(X)},
|
||
@code{write(X)}, and @code{nl} are executed repeatedly, because
|
||
backtracking is caught by the @code{repeat} goal.
|
||
|
||
The built-in @code{repeat/1} could be defined in Prolog by:
|
||
@example
|
||
repeat.
|
||
repeat :- repeat.
|
||
@end example
|
||
|
||
@item call(+@var{P}) [IS0]
|
||
@findex call/1
|
||
@syindex call/1
|
||
@cyindex call/1
|
||
If @var{P} is instantiated to an atom or a compound term, the goal
|
||
@code{call(@var{P})} is executed as if the value of @code{P} was found
|
||
instead of the call to @code{call/1}, except that any "cut" occurring in
|
||
@var{P} only cuts alternatives in the execution of @var{P}.
|
||
|
||
@item incore(+@var{P})
|
||
@findex incore/1
|
||
@syindex incore/1
|
||
@cnindex incore/1
|
||
The same as @code{call/1}.
|
||
|
||
@item call_with_args(+@var{Name},...,?@var{Ai},...)
|
||
@findex call_with_args/n
|
||
@snindex call_with_args/n
|
||
@cnindex call_with_args/n
|
||
Meta-call where @var{Name} is the name of the procedure to be called and
|
||
the @var{Ai} are the arguments. The number of arguments varies between 0
|
||
and 10.
|
||
|
||
If @var{Name} is a complex term, then @code{call_with_args/n} behaves as
|
||
@code{call/n}:
|
||
|
||
@example
|
||
call(p(X1,...,Xm), Y1,...,Yn) :- p(X1,...,Xm,Y1,...,Yn).
|
||
@end example
|
||
|
||
|
||
@item +@var{P}
|
||
The same as @code{call(@var{P})}. This feature has been kept to provide
|
||
compatibility with C-Prolog. When compiling a goal, YAP
|
||
generates a @code{call(@var{X})} whenever a variable @var{X} is found as
|
||
a goal.
|
||
|
||
@example
|
||
a(X) :- X.
|
||
@end example
|
||
@noindent
|
||
is converted to:
|
||
@example
|
||
a(X) :- call(X).
|
||
@end example
|
||
|
||
@item if(?@var{G},?@var{H},?@var{I}) [IS0]
|
||
@findex if/3
|
||
@syindex if/3
|
||
@cnindex if/3
|
||
Call goal @var{H} once per each solution of goal @var{H}. If goal
|
||
@var{H} has no solutions, call goal @var{I}.
|
||
|
||
The built-in @code{if/3} is similar to @code{->/3}, with the difference
|
||
that it will backtrack over the test goal. Consider the following
|
||
small data-base:
|
||
|
||
@example
|
||
a(1). b(a). c(x).
|
||
a(2). b(b). c(y).
|
||
@end example
|
||
|
||
Execution of an @code{if/3} query will proceed as follows:
|
||
|
||
@example
|
||
?- if(a(X),b(Y),c(Z)).
|
||
|
||
X = 1,
|
||
Y = a ? ;
|
||
|
||
X = 1,
|
||
Y = b ? ;
|
||
|
||
X = 2,
|
||
Y = a ? ;
|
||
|
||
X = 2,
|
||
Y = b ? ;
|
||
|
||
no
|
||
@end example
|
||
|
||
|
||
@noindent
|
||
The system will backtrack over the two solutions for @code{a/1} and the
|
||
two solutions for @code{b/1}, generating four solutions.
|
||
|
||
Cuts are allowed inside the first goal @var{G}, but they will only prune
|
||
over @var{G}.
|
||
|
||
If you want @var{G} to be deterministic you should use if-then-else, as
|
||
it is both more efficient and more portable.
|
||
|
||
@item once(:@var{G}) [IS0]
|
||
@findex once/1
|
||
@snindex once/1
|
||
@cnindex once/1
|
||
Execute the goal @var{G} only once. The predicate is defined by:
|
||
|
||
@example
|
||
once(G) :- call(G), !.
|
||
@end example
|
||
|
||
@noindent
|
||
Note that cuts inside @code{once/1} can only cut the other goals inside
|
||
@code{once/1}.
|
||
|
||
@item abort
|
||
@findex abort/0
|
||
@syindex abort/0
|
||
@cyindex abort/0
|
||
Abandons the execution of the current goal and returns to top level. All
|
||
break levels (see @code{break/0} below) are terminated. It is mainly
|
||
used during debugging or after a serious execution error, to return to
|
||
the top-level.
|
||
|
||
|
||
@item break
|
||
@findex break/0
|
||
@syindex break/0
|
||
@cyindex break/0
|
||
Suspends the execution of the current goal and creates a new execution
|
||
level similar to the top level, displaying the following message:
|
||
|
||
@example
|
||
[ Break (level <number>) ]
|
||
@end example
|
||
@noindent
|
||
telling the depth of the break level just entered. To return to the
|
||
previous level just type the end-of-file character or call the
|
||
end_of_file predicate. This predicate is especially useful during
|
||
debugging.
|
||
|
||
@item halt [ISO]
|
||
@findex halt/0
|
||
@syindex halt/0
|
||
@cyindex halt/0
|
||
Halts Prolog, and exits to the calling application. In YAP,
|
||
@code{halt/0} returns the exit code @code{0}.
|
||
|
||
@item halt(+ @var{I}) [ISO]
|
||
@findex halt/1
|
||
@syindex halt/1
|
||
@cnindex halt/1
|
||
Halts Prolog, and exits to the calling application returning the code
|
||
given by the integer @var{I}.
|
||
|
||
@item catch(+@var{Goal},+@var{Exception},+@var{Action}) [IS0]
|
||
@findex catch/3
|
||
@snindex catch/3
|
||
@cnindex catch/3
|
||
The goal @code{catch(@var{Goal},@var{Exception},@var{Action})} tries to
|
||
execute goal @var{Goal}. If during its execution, @var{Goal} throws an
|
||
exception @var{E'} and this exception unifies with @var{Exception}, the
|
||
exception is considered to be caught and @var{Action} is executed. If
|
||
the exception @var{E'} does not unify with @var{Exception}, control
|
||
again throws the exception.
|
||
|
||
The top-level of YAP maintains a default exception handler that
|
||
is responsible to capture uncaught exceptions.
|
||
|
||
@item throw(+@var{Ball}) [ISO]
|
||
@findex throw/1
|
||
@snindex throw/1
|
||
@cnindex throw/1
|
||
The goal @code{throw(@var{Ball})} throws an exception. Execution is
|
||
stopped, and the exception is sent to the ancestor goals until reaching
|
||
a matching @code{catch/3}, or until reaching top-level.
|
||
|
||
@item garbage_collect
|
||
@findex garbage_collect/0
|
||
@syindex garbage_collect/0
|
||
@cnindex garbage_collect/0
|
||
The goal @code{garbage_collect} forces a garbage collection.
|
||
|
||
@item garbage_collect_atoms
|
||
@findex garbage_collect_atoms/0
|
||
@syindex garbage_collect_atoms/0
|
||
@cnindex garbage_collect_atoms/0
|
||
The goal @code{garbage_collect} forces a garbage collection of the atoms
|
||
in the data-base. Currently, only atoms are recovered.
|
||
|
||
@item gc
|
||
@findex gc/0
|
||
@syindex gc/0
|
||
@cnindex gc/0
|
||
The goal @code{gc} enables garbage collection. The same as
|
||
@code{yap_flag(gc,on)}.
|
||
|
||
@item nogc
|
||
@findex nogc/0
|
||
@syindex nogc/0
|
||
@cnindex nogc/0
|
||
The goal @code{nogc} disables garbage collection. The same as
|
||
@code{yap_flag(gc,off)}.
|
||
|
||
@item grow_heap(+@var{Size})
|
||
@snindex grow_heap/1
|
||
@cnindex grow_heap/1
|
||
Increase heap size @var{Size} kilobytes.
|
||
|
||
@item grow_stack(+@var{Size})
|
||
@findex grow_stack/1
|
||
@snindex grow_stack/1
|
||
@cnindex grow_stack/1
|
||
Increase stack size @var{Size} kilobytes.
|
||
|
||
@end table
|
||
|
||
@node Undefined Procedures, Testing Terms, Control, Top
|
||
@section Handling Undefined Procedures
|
||
|
||
A predicate in a module is said to be undefined if there are no clauses
|
||
defining the predicate, and if the predicate has not been declared to be
|
||
dynamic. What YAP does when trying to execute undefined predicates can
|
||
be specified through three different ways:
|
||
@itemize @bullet
|
||
@item By setting an YAP flag, through the @code{yap_flag/2} or
|
||
@code{set_prolog_flag/2} built-ins. This solution generalizes the
|
||
ISO standard.
|
||
@item By using the @code{unknown/2} built-in (this solution is
|
||
compatible with previous releases of YAP).
|
||
@item By defining clauses for the hook predicate
|
||
@code{user:unknown_predicate_handler/3}. This solution is compatible
|
||
with SICStus Prolog.
|
||
@end itemize
|
||
|
||
In more detail:
|
||
@table @code
|
||
@item unknown(-@var{O},+@var{N})
|
||
@findex unknown/2
|
||
@saindex unknown/2
|
||
@cnindex unknown/2
|
||
Specifies an handler to be called is a program tries to call an
|
||
undefined static procedure @var{P}.
|
||
|
||
The arity of @var{N} may be zero or one. If the arity is @code{0}, the
|
||
new action must be one of @code{fail}, @code{warning}, or
|
||
@code{error}. If the arity is @code{1}, @var{P} is an user-defined
|
||
handler and at run-time, the argument to the handler @var{P} will be
|
||
unified with the undefined goal. Note that @var{N} must be defined prior
|
||
to calling @code{unknown/2}, and that the single argument to @var{N} must
|
||
be unbound.
|
||
|
||
In YAP, the default action is to @code{fail} (note that in the ISO
|
||
Prolog standard the default action is @code{error}).
|
||
|
||
After defining @code{undefined/1} by:
|
||
@example
|
||
undefined(A) :- format('Undefined predicate: ~w~n',[A]), fail.
|
||
@end example
|
||
@noindent
|
||
and executing the goal:
|
||
@example
|
||
unknown(U,undefined(X)).
|
||
@end example
|
||
@noindent
|
||
a call to a predicate for which no clauses were defined will result in
|
||
the output of a message of the form:
|
||
@example
|
||
Undefined predicate: user:xyz(A1,A2)
|
||
@end example
|
||
@noindent
|
||
followed by the failure of that call.
|
||
|
||
@item yap_flag(unknown,+@var{SPEC})
|
||
Alternatively, one can use @code{yap_flag/2},
|
||
@code{current_prolog_flag/2}, or @code{set_prolog_flag/2}, to set this
|
||
functionality. In this case, the first argument for the built-ins should
|
||
be @code{unknown}, and the second argument should be either
|
||
@code{error}, @code{warning}, @code{fail}, or a goal.
|
||
|
||
@item user:unknown_predicate_handler(+G,+M,?NG)
|
||
@findex unknown_predicate_handler/3
|
||
@syindex unknown_predicate_handler/3
|
||
@cnindex unknown_predicate_handler/3
|
||
The user may also define clauses for
|
||
@code{user:unknown_predicate_handler/3} hook predicate. This
|
||
user-defined procedure is called before any system processing for the
|
||
undefined procedure, with the first argument @var{G} set to the current
|
||
goal, and the second @var{M} set to the current module. The predicate
|
||
@var{G} will be called from within the user module.
|
||
|
||
If @code{user:unknown_predicate_handler/3} succeeds, the system will
|
||
execute @var{NG}. If @code{user:unknown_predicate_handler/3} fails, the
|
||
system will execute default action as specified by @code{unknown/2}.
|
||
@end table
|
||
|
||
@node Testing Terms, Comparing Terms, Undefined Procedures, Top
|
||
@section Predicates on terms
|
||
|
||
@table @code
|
||
|
||
@item var(@var{T}) [ISO]
|
||
@findex var/1
|
||
@syindex var/1
|
||
@cyindex var/1
|
||
Succeeds if @var{T} is currently a free variable, otherwise fails.
|
||
|
||
@item atom(@var{T}) [ISO]
|
||
@findex atom/1
|
||
@syindex atom/1
|
||
@cyindex atom/1
|
||
Succeeds if and only if @var{T} is currently instantiated to an atom.
|
||
|
||
@item atomic(T) [ISO]
|
||
@findex atomic/1
|
||
@syindex atomic/1
|
||
@cyindex atomic/1
|
||
Checks whether @var{T} is an atomic symbol (atom or number).
|
||
|
||
@item compound(@var{T}) [ISO]
|
||
@findex compound/1
|
||
@syindex compound/1
|
||
@cnindex compound/1
|
||
Checks whether @var{T} is a compound term.
|
||
|
||
@item db_reference(@var{T})
|
||
@findex db_reference/1C
|
||
@syindex db_reference/1
|
||
@cyindex db_reference/1
|
||
Checks whether @var{T} is a database reference.
|
||
|
||
@item float(@var{T}) [ISO]
|
||
@findex float/1
|
||
@syindex float/1
|
||
@cnindex float/1
|
||
Checks whether @var{T} is a floating point number.
|
||
|
||
@item integer(@var{T}) [ISO]
|
||
@findex integer/1
|
||
@syindex integer/1
|
||
@cyindex integer/1
|
||
Succeeds if and only if @var{T} is currently instantiated to an integer.
|
||
|
||
@item nonvar(@var{T}) [ISO]
|
||
@findex nonvar/1
|
||
@syindex nonvar/1
|
||
@cyindex nonvar/1
|
||
The opposite of @code{var(@var{T})}.
|
||
|
||
@item number(@var{T}) [ISO]
|
||
@findex number/1
|
||
@syindex number/1
|
||
@cyindex number/1
|
||
Checks whether @code{T} is an integer or a float.
|
||
|
||
@item primitive(@var{T})
|
||
@findex primitive/1
|
||
@syindex primitive/1
|
||
@cyindex primitive/1
|
||
Checks whether @var{T} is an atomic term or a database reference.
|
||
|
||
@item simple(@var{T})
|
||
@findex simple/1
|
||
@syindex simple/1
|
||
@cnindex simple/1
|
||
Checks whether @var{T} is unbound, an atom, or a number.
|
||
|
||
@item callable(@var{T})
|
||
@findex callable/1
|
||
@syindex callable/1
|
||
@cnindex callable/1
|
||
Checks whether @var{T} is a callable term, that is, an atom or a
|
||
compound term.
|
||
|
||
@item name(@var{A},@var{L})
|
||
@findex name/2
|
||
@syindex name/2
|
||
@cyindex name/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} will
|
||
be unified with an atomic symbol and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@example
|
||
name(yap,L).
|
||
@end example
|
||
@noindent
|
||
will return:
|
||
@example
|
||
L = [121,97,112].
|
||
@end example
|
||
@noindent
|
||
and
|
||
@example
|
||
name(3,L).
|
||
@end example
|
||
@noindent
|
||
will return:
|
||
@example
|
||
L = [51].
|
||
@end example
|
||
|
||
@item atom_chars(?@var{A},?@var{L}) [ISO]
|
||
@findex atom_chars/2
|
||
@saindex atom_chars/2
|
||
@cnindex atom_chars/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} must
|
||
be unifiable with an atom, and the argument @var{L} with the list of the
|
||
ASCII codes for the characters of the external representation of @var{A}.
|
||
|
||
The ISO-Prolog standard dictates that @code{atom_chars/2} should unify
|
||
the second argument with a list of one-char atoms, and not the character
|
||
codes. For compatibility with previous versions of YAP, and
|
||
with other Prolog implementations, YAP unifies the second
|
||
argument with the character codes, as in @code{atom_codes/2}. Use the
|
||
@code{set_prolog_flag(to_chars_mode,iso)} to obtain ISO standard
|
||
compatibility.
|
||
|
||
@item atom_codes(?@var{A},?@var{L}) [ISO]
|
||
@findex atom_codes/2
|
||
@syindex atom_codes/2
|
||
@cnindex atom_codes/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} will
|
||
be unified with an atom and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@item atom_concat(+@var{As},?@var{A})
|
||
@findex atom_concat/2
|
||
@syindex atom_concat/2
|
||
@cnindex atom_concat/2
|
||
The predicate holds when the first argument is a list of atoms, and the
|
||
second unifies with the atom obtained by concatenating all the atoms in
|
||
the first list.
|
||
|
||
@item atomic_concat(+@var{As},?@var{A})
|
||
@findex atomic_concat/2
|
||
@snindex atomic_concat/2
|
||
@cnindex atomic_concat/2
|
||
The predicate holds when the first argument is a list of atoms, and
|
||
the second unifies with the atom obtained by concatenating all the
|
||
atomic terms in the first list. The first argument thus may contain
|
||
atoms or numbers.
|
||
|
||
@item atom_concat(+@var{A1},+@var{A2},?@var{A})
|
||
@findex atom_concat/3
|
||
@syindex atom_concat/3
|
||
@cnindex atom_concat/3
|
||
The predicate holds when the first argument and second argument are
|
||
atoms, and the third unifies with the atom obtained by concatenating
|
||
the first two arguments.
|
||
|
||
@item atom_length(+@var{A},?@var{I}) [ISO]
|
||
@findex atom_length/2
|
||
@snindex atom_length/2
|
||
@cnindex atom_length/2
|
||
The predicate holds when the first argument is an atom, and the second
|
||
unifies with the number of characters forming that atom.
|
||
|
||
@item atom_concat(?@var{A1},?@var{A2},?@var{A12}) [ISO]
|
||
@findex atom_concat/3
|
||
@snindex atom_concat/3
|
||
@cnindex atom_concat/3
|
||
The predicate holds when the third argument unifies with an atom, and
|
||
the first and second unify with atoms such that their representations
|
||
concatenated are the representation for @var{A12}.
|
||
|
||
If @var{A1} and @var{A2} are unbound, the built-in will find all the atoms
|
||
that concatenated give @var{A12}.
|
||
|
||
@item number_chars(?@var{I},?@var{L})
|
||
@findex number_chars/2
|
||
@saindex number_chars/2
|
||
@cnindex number_chars/2
|
||
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{I} must
|
||
be unifiable with a number, and the argument @var{L} with the list of the
|
||
ASCII codes for the characters of the external representation of @var{I}.
|
||
|
||
The ISO-Prolog standard dictates that @code{number_chars/2} should unify
|
||
the second argument with a list of one-char atoms, and not the character
|
||
codes. For compatibility with previous versions of YAP, and
|
||
with other Prolog implementations, YAP unifies the second
|
||
argument with the character codes, as in @code{number_codes/2}. Use the
|
||
@code{set_prolog_flag(to_chars_mode,iso)} to obtain ISO standard
|
||
compatibility.
|
||
|
||
@item number_codes(?@var{A},?@var{L}) [ISO]
|
||
@findex number_codes/2
|
||
@syindex number_codes/2
|
||
@cnindex number_codes/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A}
|
||
will be unified with a number and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@item number_atom(?@var{I},?@var{L})
|
||
@findex number_atom/2
|
||
@snindex number_atom/2
|
||
@cnindex number_atom/2
|
||
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{I} must
|
||
be unifiable with a number, and the argument @var{L} must be unifiable
|
||
with an atom representing the number.
|
||
|
||
@item char_code(?@var{A},?@var{I}) [ISO]
|
||
@findex char_code/2
|
||
@syindex char_code/2
|
||
@cnindex char_code/2
|
||
The built-in succeeds with @var{A} bound to character represented as an
|
||
atom, and @var{I} bound to the character code represented as an
|
||
integer. At least, one of either @var{A} or @var{I} must be bound before
|
||
the call.
|
||
|
||
@item sub_atom(+@var{A},?@var{Bef}, ?@var{Size}, ?@var{After}, ?@var{At_out}) [ISO]
|
||
@findex sub_atom/5
|
||
@snindex sub_atom/5
|
||
@cnindex sub_atom/5
|
||
True when @var{A} and @var{At_out} are atoms such that the name of
|
||
@var{At_out} has size @var{Size} and is a substring of the name of
|
||
@var{A}, such that @var{Bef} is the number of characters before and
|
||
@var{After} the number of characters afterwards.
|
||
|
||
Note that @var{A} must always be known, but @var{At_out} can be unbound when
|
||
calling this built-in. If all the arguments for @code{sub_atom/5} but @var{A}
|
||
are unbound, the built-in will backtrack through all possible
|
||
substrings of @var{A}.
|
||
|
||
@item numbervars(@var{T},+@var{N1},-@var{Nn})
|
||
@findex numbervars/3
|
||
@syindex numbervars/3
|
||
@cnindex numbervars/3
|
||
Instantiates each variable in term @var{T} to a term of the form:
|
||
@code{'$VAR'(@var{I})}, with @var{I} increasing from @var{N1} to @var{Nn}.
|
||
|
||
@item ground(@var{T})
|
||
@findex ground/1
|
||
@syindex ground/1
|
||
@cnindex ground/1
|
||
Succeeds if there are no free variables in the term @var{T}.
|
||
|
||
@item arg(+@var{N},+@var{T},@var{A}) [ISO]
|
||
@findex arg/3
|
||
@syindex arg/3
|
||
@cnindex arg/3
|
||
Succeeds if the argument @var{N} of the term @var{T} unifies with
|
||
@var{A}. The arguments are numbered from 1 to the arity of the term.
|
||
|
||
The current version will generate an error if @var{T} or @var{N} are
|
||
unbound, if @var{T} is not a compound term, of if @var{N} is not a positive
|
||
integer. Note that previous versions of YAP would fail silently
|
||
under these errors.
|
||
|
||
@item functor(@var{T},@var{F},@var{N})
|
||
@findex functor/3
|
||
@syindex functor/3
|
||
@cyindex functor/3
|
||
The top functor of term @var{T} is named @var{F} and has arity @var{N}.
|
||
|
||
When @var{T} is not instantiated, @var{F} and @var{N} must be. If
|
||
@var{N} is 0, @var{F} must be an atomic symbol, which will be unified
|
||
with @var{T}. If @var{N} is not 0, then @var{F} must be an atom and
|
||
@var{T} becomes instantiated to the most general term having functor
|
||
@var{F} and arity @var{N}. If @var{T} is instantiated to a term then
|
||
@var{F} and @var{N} are respectively unified with its top functor name
|
||
and arity.
|
||
|
||
In the current version of YAP the arity @var{N} must be an
|
||
integer. Previous versions allowed evaluable expressions, as long as the
|
||
expression would evaluate to an integer. This feature is not available
|
||
in the ISO Prolog standard.
|
||
|
||
@item @var{T} =.. @var{L} [ISO]
|
||
@findex =../2
|
||
@syindex =../2
|
||
@cyindex =../2
|
||
The list @var{L} is built with the functor and arguments of the term
|
||
@var{T}. If @var{T} is instantiated to a variable, then @var{L} must be
|
||
instantiated either to a list whose head is an atom, or to a list
|
||
consisting of just a number.
|
||
|
||
@item @var{X} = @var{Y} [ISO]
|
||
@findex =/2
|
||
@syindex =/2
|
||
@cnindex =/2
|
||
Tries to unify terms @var{X} and @var{Y}.
|
||
|
||
@item @var{X} \= @var{Y} [ISO]
|
||
@findex \=/2
|
||
@snindex \=/2
|
||
@cnindex \=/2
|
||
Succeeds if terms @var{X} and @var{Y} are not unifiable.
|
||
|
||
@item unify_with_occurs_check(?T1,?T2) [ISO]
|
||
@findex unify_with_occurs_check/2
|
||
@syindex unify_with_occurs_check/2
|
||
@cnindex unify_with_occurs_check/2
|
||
Obtain the most general unifier of terms @var{T1} and @var{T2}, if there
|
||
is one.
|
||
|
||
This predicate implements the full unification algorithm. An example:n
|
||
@example
|
||
unify_with_occurs_check(a(X,b,Z),a(X,A,f(B)).
|
||
@end example
|
||
@noindent
|
||
will succeed with the bindings @code{A = b} and @code{Z = f(B)}. On the
|
||
other hand:
|
||
@example
|
||
unify_with_occurs_check(a(X,b,Z),a(X,A,f(Z)).
|
||
@end example
|
||
@noindent
|
||
would fail, because @code{Z} is not unifiable with @code{f(Z)}. Note that
|
||
@code{(=)/2} would succeed for the previous examples, giving the following
|
||
bindings @code{A = b} and @code{Z = f(Z)}.
|
||
|
||
|
||
@item copy_term(?@var{TI},-@var{TF}) [ISO]
|
||
@findex copy_term/2
|
||
@syindex copy_term/2
|
||
@cnindex copy_term/2
|
||
Term @var{TF} is a variant of the original term @var{TI}, such that for
|
||
each variable @var{V} in the term @var{TI} there is a new variable @var{V'}
|
||
in term @var{TF}.
|
||
|
||
@end table
|
||
|
||
@node Comparing Terms, Arithmetic, Testing Terms, Top
|
||
@section Comparing Terms
|
||
|
||
The following predicates are used to compare and order terms, using the
|
||
standard ordering:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
variables come before numbers, numbers come before atoms which in turn
|
||
come before compound terms, i.e.: variables @@< numbers @@< atoms @@<
|
||
compound terms.
|
||
@item
|
||
variables are roughly ordered by "age" (the "oldest" variable is put
|
||
first);
|
||
@item
|
||
floating point numbers are sorted in increasing order;
|
||
@item
|
||
Integers are sorted in increasing order;
|
||
@item
|
||
atoms are sorted in lexicographic order;
|
||
@item
|
||
compound terms are ordered first by name, then by arity of the main
|
||
functor, and finally by their arguments in left-to-right order.
|
||
@end itemize
|
||
|
||
@table @code
|
||
|
||
@item compare(@var{C},@var{X},@var{Y})
|
||
@findex compare/3
|
||
@syindex compare/3
|
||
@cyindex compare/3
|
||
As a result of comparing @var{X} and @var{Y}, @var{C} may take one of
|
||
the following values:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
@code{=} if @var{X} and @var{Y} are identical;
|
||
@item
|
||
@code{<} if @var{X} precedes @var{Y} in the defined order;
|
||
@item
|
||
@code{>} if @var{Y} precedes @var{X} in the defined order;
|
||
@end itemize
|
||
|
||
@item @var{X} == @var{Y} [ISO]
|
||
@findex ==/2
|
||
@syindex ==/2
|
||
@cyindex ==/2
|
||
Succeeds if terms @var{X} and @var{Y} are strictly identical. The
|
||
difference between this predicate and @code{=/2} is that, if one of the
|
||
arguments is a free variable, it only succeeds when they have already
|
||
been unified.
|
||
|
||
@example
|
||
?- X == Y.
|
||
@end example
|
||
@noindent
|
||
fails, but,
|
||
@example
|
||
?- X = Y, X == Y.
|
||
@end example
|
||
@noindent
|
||
succeeds.
|
||
@example
|
||
?- X == 2.
|
||
@end example
|
||
@noindent
|
||
fails, but,
|
||
@example
|
||
?- X = 2, X == 2.
|
||
@end example
|
||
@noindent
|
||
succeeds.
|
||
|
||
|
||
@item @var{X} \== @var{Y} [ISO]
|
||
@findex \==/2
|
||
@syindex \==/2
|
||
@cyindex \==/2
|
||
Terms @var{X} and @var{Y} are not strictly identical.
|
||
|
||
@item @var{X} @@< @var{Y} [ISO]
|
||
@findex @@</2
|
||
@syindex @@</2
|
||
@cyindex @@</2
|
||
Term @var{X} precedes term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@=< @var{Y} [ISO]
|
||
@findex @@=</2
|
||
@syindex @@</2
|
||
@cyindex @@</2
|
||
Term @var{X} does not follow term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@> @var{Y} [ISO]
|
||
@findex @@>/2
|
||
@syindex @@>/2
|
||
@cyindex @@>/2
|
||
Term @var{X} follows term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@>= @var{Y} [ISO]
|
||
@findex @@>=/2
|
||
@syindex @@>=/2
|
||
@cyindex @@>=/2
|
||
Term @var{X} does not precede term @var{Y} in the standard order.
|
||
|
||
@item sort(+@var{L},-@var{S})
|
||
@findex sort/2
|
||
@syindex sort/2
|
||
@cyindex sort/2
|
||
Unifies @var{S} with the list obtained by sorting @var{L} and merging
|
||
identical (in the sense of @code{==}) elements.
|
||
|
||
@item keysort(+@var{L},@var{S})
|
||
@findex keysort/2
|
||
@syindex keysort/2
|
||
@cyindex keysort/2
|
||
Assuming L is a list of the form @code{@var{Key}-@var{Value}},
|
||
@code{keysort(+@var{L},@var{S})} unifies @var{S} with the list obtained
|
||
from @var{L}, by sorting its elements according to the value of
|
||
@var{Key}.
|
||
@example
|
||
?- keysort([3-a,1-b,2-c,1-a,1-b],S).
|
||
@end example
|
||
@noindent
|
||
would return:
|
||
@example
|
||
S = [1-b,1-a,1-b,2-c,3-a]
|
||
@end example
|
||
|
||
@item length(?@var{L},?@var{S})
|
||
@findex length/2
|
||
@syindex length/2
|
||
@cyindex length/2
|
||
Unify the well-defined list @var{L} with its length. The procedure can
|
||
be used to find the length of a pre-defined list, or to build a list
|
||
of length @var{S}.
|
||
|
||
@end table
|
||
|
||
@node Arithmetic, I/O, Comparing Terms, Top
|
||
@section Arithmetic
|
||
Arithmetic expressions in YAP may use the following operators
|
||
or @i{evaluable predicates}:
|
||
|
||
@table @code
|
||
|
||
@item +@var{X}
|
||
The value of @var{X} itself.
|
||
|
||
@item -@var{X} [ISO]
|
||
Symmetric value.
|
||
|
||
@item @var{X}+@var{Y} [ISO]
|
||
Sum.
|
||
|
||
@item @var{X}-@var{Y} [ISO]
|
||
Difference.
|
||
|
||
@item @var{X}*@var{Y} [ISO]
|
||
Product.
|
||
|
||
@item @var{X}/@var{Y} [ISO]
|
||
Quotient.
|
||
|
||
@item @var{X}//@var{Y} [ISO]
|
||
Integer quotient.
|
||
|
||
@item @var{X} mod @var{Y} [ISO]
|
||
Integer remainder.
|
||
|
||
@item @var{X} rem @var{Y}
|
||
Integer remainder, the same as @code{mod}.
|
||
|
||
@item exp(@var{X}) [ISO]
|
||
Natural exponential.
|
||
|
||
@item log(@var{X}) [ISO]
|
||
Natural logarithm.
|
||
|
||
@item log10(@var{X})
|
||
Decimal logarithm.
|
||
|
||
@item sqrt(@var{X}) [ISO]
|
||
Square root.
|
||
|
||
@item sin(@var{X}) [ISO]
|
||
Sine.
|
||
|
||
@item cos(@var{X}) [ISO]
|
||
Cosine.
|
||
|
||
@item tan(@var{X})
|
||
Tangent.
|
||
|
||
@item asin(@var{X})
|
||
Arc sine.
|
||
|
||
@item acos(@var{X})
|
||
Arc cosine.
|
||
|
||
@item atan(@var{X}) [ISO]
|
||
Arc tangent.
|
||
|
||
@item atan2(@var{X})
|
||
Four-quadrant arc tangent.
|
||
|
||
@item sinh(@var{X})
|
||
Hyperbolic sine.
|
||
|
||
@item cosh(@var{X})
|
||
Hyperbolic cosine.
|
||
|
||
@item tanh(@var{X})
|
||
Hyperbolic tangent.
|
||
|
||
@item asinh(@var{X})
|
||
Hyperbolic arc sine.
|
||
|
||
@item acosh(@var{X})
|
||
Hyperbolic arc cosine.
|
||
|
||
@item atanh(@var{X})
|
||
Hyperbolic arc tangent.
|
||
|
||
@item integer(@var{X}) [ISO]
|
||
If @var{X} evaluates to a float, the integer between the value of @var{X}
|
||
and 0 closest to the value of @var{X}, else if @var{X} evaluates to an
|
||
integer, the value of @var{X}.
|
||
|
||
@item float(@var{X}) [ISO]
|
||
If @var{X} evaluates to an integer, the corresponding float, else the float
|
||
itself.
|
||
|
||
@item float_fractional_part(@var{X}) [ISO]
|
||
The fractional part of the floating point number @var{X}, or @code{0.0}
|
||
if @var{X} is an integer. In the @code{iso} language mode,
|
||
@var{X} must be an integer.
|
||
|
||
@item float_integer_part(@var{X}) [ISO]
|
||
The float giving the integer part of the floating point number @var{X},
|
||
or @var{X} if @var{X} is an integer. In the @code{iso} language mode,
|
||
@var{X} must be an integer.
|
||
|
||
@item abs(@var{X}) [ISO]
|
||
The absolute value of @var{X}.
|
||
|
||
@item ceiling(@var{X}) [ISO]
|
||
The float that is the smallest integral value not smaller than @var{X}.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number and the result is an integer.
|
||
|
||
@item floor(@var{X}) [ISO]
|
||
The float that is the greatest integral value not greater than @var{X}.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number and the result is an integer.
|
||
|
||
@item round(@var{X}) [ISO]
|
||
The nearest integral value to @var{X}. If @var{X} is
|
||
equidistant to two integers, it will be rounded to the closest even
|
||
integral value.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number, the result is an integer and it the float is equidistant
|
||
it is rounded up, that is, to the least integer greater than @var{X}.
|
||
|
||
@item sign(@var{X}) [ISO]
|
||
Return 1 if the @var{X} evaluates to a positive integer, 0 it if
|
||
evaluates to 0, and -1 if it evaluates to a negative integer. If @var{X}
|
||
evaluates to a floating-point number return 1.0 for a positive @var{X},
|
||
0.0 for 0.0, and -1.0 otherwise.
|
||
|
||
@item truncate(@var{X})
|
||
The float that is the integral value between @var{X} and 0 closest to
|
||
@var{X}.
|
||
|
||
@item max(@var{X},@var{Y})
|
||
The greater value of @var{X} and @var{Y}.
|
||
|
||
@item min(@var{X},@var{Y})
|
||
The lesser value of @var{X} and @var{Y}.
|
||
|
||
@item @var{X} ^ @var{Y}
|
||
@var{X} raised to the power of @var{Y}, (from the C-Prolog syntax).
|
||
|
||
@item exp(@var{X},@var{Y})
|
||
@var{X} raised to the power of @var{Y}, (from the Quintus Prolog syntax).
|
||
|
||
@item @var{X} ** @var{Y} [ISO]
|
||
@var{X} raised to the power of @var{Y} (from ISO).
|
||
|
||
@item @var{X} /\ @var{Y} [ISO]
|
||
Integer bitwise conjunction.
|
||
|
||
@item @var{X} \/ @var{Y} [ISO]
|
||
Integer bitwise disjunction.
|
||
|
||
@item @var{X} # @var{Y} [ISO]
|
||
Integer bitwise exclusive disjunction.
|
||
|
||
@item @var{X} << @var{Y}
|
||
Integer bitwise left logical shift of @var{X} by @var{Y} places.
|
||
|
||
@item @var{X} >> @var{Y} [ISO]
|
||
Integer bitwise right logical shift of @var{X} by @var{Y} places.
|
||
|
||
@item \ @var{X} [ISO]
|
||
Integer bitwise negation.
|
||
|
||
@item gcd(@var{X},@var{Y})
|
||
The greatest common divisor of the two integers @var{X} and @var{Y}.
|
||
|
||
@item msb(@var{X})
|
||
The most significant bit of the integer @var{X}.
|
||
|
||
@item [@var{X}]
|
||
Evaluates to @var{X} for expression @var{X}. Useful because character
|
||
strings in Prolog are lists of character codes.
|
||
|
||
@example
|
||
X is Y*10+C-"0"
|
||
@end example
|
||
@noindent
|
||
is the same as
|
||
@example
|
||
X is Y*10+C-[48].
|
||
@end example
|
||
@noindent
|
||
which would be evaluated as:
|
||
@example
|
||
X is Y*10+C-48.
|
||
@end example
|
||
|
||
@end table
|
||
|
||
Besides numbers and the arithmetic operators described above, certain
|
||
atoms have a special meaning when present in arithmetic expressions:
|
||
|
||
@table @code
|
||
@item pi
|
||
The value of @emph{pi}, the ratio of a circle's circumference to its
|
||
diameter.
|
||
|
||
@item e
|
||
The base of the natural logarithms.
|
||
|
||
@item inf
|
||
Infinity according to the IEEE Floating-Point standard. Note that
|
||
evaluating this term will generate a domain error in the @code{iso}
|
||
language mode.
|
||
|
||
@item nan
|
||
Not-a-number according to the IEEE Floating-Point standard. Note that
|
||
evaluating this term will generate a domain error in the @code{iso}
|
||
language mode.
|
||
|
||
@item cputime
|
||
CPU time in seconds, since YAP was invoked.
|
||
|
||
@item heapused
|
||
Heap space used, in bytes.
|
||
|
||
@item local
|
||
Local stack in use, in bytes.
|
||
|
||
@item global
|
||
Global stack in use, in bytes.
|
||
|
||
@item random
|
||
A "random" floating point number between 0 and 1.
|
||
|
||
@end table
|
||
|
||
The primitive YAP predicates involving arithmetic expressions are:
|
||
|
||
@table @code
|
||
|
||
@item @var{X} is +@var{Y} [2]
|
||
@findex is/2
|
||
@syindex is/2
|
||
@caindex is/2
|
||
This predicate succeeds iff the result of evaluating the expression
|
||
@var{Y} unifies with @var{X}. This is the predicate normally used to
|
||
perform evaluation of arithmetic expressions:
|
||
|
||
@example
|
||
X is 2+3*4
|
||
@end example
|
||
@noindent
|
||
succeeds with @code{X = 14}.
|
||
|
||
@item +@var{X} < +@var{Y} [ISO]
|
||
@findex </2
|
||
@syindex </2
|
||
@cyindex </2
|
||
The value of the expression @var{X} is less than the value of expression
|
||
@var{Y}.
|
||
|
||
@item +@var{X} =< +@var{Y} [ISO]
|
||
@findex =</2
|
||
@syindex =</2
|
||
@cyindex =</2
|
||
The value of the expression @var{X} is less than or equal to the value
|
||
of expression @var{Y}.
|
||
|
||
|
||
@item +@var{X} > +@var{Y} [ISO]
|
||
@findex >/2
|
||
@syindex >/2
|
||
@cyindex >/2
|
||
The value of the expression @var{X} is greater than the value of
|
||
expression @var{Y}.
|
||
|
||
@item +@var{X} >= +@var{Y} [ISO]
|
||
@findex >=/2
|
||
@syindex >=/2
|
||
@cyindex >=/2
|
||
The value of the expression @var{X} is greater than or equal to the
|
||
value of expression @var{Y}.
|
||
|
||
@item +@var{X} =:= +@var{Y} [ISO]
|
||
@findex =:=/2
|
||
@syindex =:=/2
|
||
@cyindex =:=/2
|
||
The value of the expression @var{X} is equal to the value of expression
|
||
@var{Y}.
|
||
|
||
@item +@var{X} =\= +@var{Y} [ISO]
|
||
@findex =\=/2
|
||
@syindex =\=/2
|
||
@cyindex =\=/2
|
||
The value of the expression @var{X} is different from the value of
|
||
expression @var{Y}.
|
||
|
||
@item srandom(+@var{X})
|
||
@findex srandom/1
|
||
@snindex srandom/1
|
||
@cnindex srandom/1
|
||
Use the argument @var{X} as a new seed for YAP's random number
|
||
generator. The argument should be an integer, but floats are acceptable.
|
||
@end table
|
||
|
||
@noindent
|
||
@strong{Notes:}
|
||
|
||
@itemize @bullet
|
||
@item
|
||
In contrast to previous versions of Yap, Yap4 @emph{does not} convert
|
||
automatically between integers and floats.
|
||
@item
|
||
arguments to trigonometric functions are expressed in radians.
|
||
@item
|
||
if a (non-instantiated) variable occurs in an arithmetic expression
|
||
YAP will generate an exception. If no error handler is
|
||
available, execution will be thrown back to the top-level.
|
||
@end itemize
|
||
|
||
|
||
@node I/O, Database, Arithmetic, Top
|
||
@section I/O Predicates
|
||
|
||
Some of the I/O predicates described below will in certain conditions
|
||
provide error messages and abort only if the file_errors flag is set.
|
||
If this flag is cleared the same predicates will just fail. Details on
|
||
setting and clearing this flag are given under 7.7.
|
||
|
||
@menu
|
||
|
||
Subnodes of Input/Output
|
||
* Streams and Files:: Handling Streams and Files
|
||
* C-Prolog File Handling:: C-Prolog Compatible File Handling
|
||
* I/O of Terms:: Input/Output of terms
|
||
* I/O of Characters:: Input/Output of Characters
|
||
* I/O for Streams:: Input/Output using Streams
|
||
* C-Prolog to Terminal:: C-Prolog compatible Character I/O to terminal
|
||
* I/O Control:: Controlling your Input/Output
|
||
* Sockets:: Using Sockets from Yap
|
||
|
||
@end menu
|
||
|
||
@node Streams and Files, C-Prolog File Handling, , I/O
|
||
@subsection Handling Streams and Files
|
||
|
||
@table @code
|
||
|
||
@item open(+@var{F},+@var{M},-@var{S}) [ISO]
|
||
@findex open/3
|
||
@syindex open/3
|
||
@cnindex open/3
|
||
Opens the file with name @var{F} in mode @var{M} ('read', 'write' or
|
||
'append'), returning @var{S} unified with the stream name.
|
||
|
||
At most, there are 17 streams opened at the same time. Each stream is
|
||
either an input or an output stream but not both. There are always 3
|
||
open streams: @code{user_input} for reading, @code{user_output} for writing
|
||
and @code{user_error} for writing. If there is no ambiguity, the atoms
|
||
@code{user_input} and @code{user_output} may be referred to as @code{user}.
|
||
|
||
The @code{file_errors} flag controls whether errors are reported when in
|
||
mode 'read' or 'append' the file @var{F} does not exist or is not
|
||
readable, and whether in mode 'write' or 'append' the file is not
|
||
writable.
|
||
|
||
@item open(+@var{F},+@var{M},-@var{S},+@var{Opts}) [ISO]
|
||
@findex open/4
|
||
@saindex open/4
|
||
@cnindex open/4
|
||
Opens the file with name @var{F} in mode @var{M} ('read', 'write' or
|
||
'append'), returning @var{S} unified with the stream name, and following
|
||
these options:
|
||
|
||
@table @code
|
||
|
||
@item type(+@var{T})
|
||
Specify whether the stream is a @code{text} stream (default), or a
|
||
@code{binary} stream.
|
||
|
||
@item reposition(+@var{Bool})
|
||
Specify whether it is possible to reposition the stream (@code{true}), or
|
||
not (@code{false}). By default, YAP enables repositioning for all
|
||
files, except terminal files and sockets.
|
||
|
||
@item eof_action(+@var{Action})
|
||
Specify the action to take if attempting to input characters from a
|
||
stream where we have previously found an @code{end-of-file}. The possible
|
||
actions are @code{error}, that raises an error, @code{reset}, that tries to
|
||
reset the stream and is used for @code{tty} type files, and @code{eof_code},
|
||
which generates a new @code{end-of-file} (default for non-tty files).
|
||
|
||
@item alias(+@var{Name})
|
||
Specify an alias to the stream. The alias @t{Name} must be an atom. The
|
||
alias can be used instead of the stream descriptor for every operation
|
||
concerning the stream.
|
||
|
||
The operation will fail and give an error if the alias name is already
|
||
in use. YAP allows several aliases for the same file, but only
|
||
one is returned by @code{stream_property/2}
|
||
@end table
|
||
|
||
@item close(+@var{S}) [ISO]
|
||
@findex close/1
|
||
@syindex close/1
|
||
@cyindex close/1
|
||
Closes the stream @var{S}. If @var{S} does not stand for a stream
|
||
currently opened an error is reported. The streams @code{user_input},
|
||
@code{user_output}, and @code{user_error} can never be closed.
|
||
|
||
By default, give a file name, @code{close/1} will also try to close a
|
||
corresponding open stream. This feature is not available in ISO or
|
||
SICStus languages mode and is deprecated.
|
||
|
||
@item close(+@var{S},+@var{O}) [ISO]
|
||
@findex close/2
|
||
@saindex close/2
|
||
@cnindex close/2
|
||
Closes the stream @var{S}, following options @var{O}.
|
||
|
||
The only valid options are @code{force(true)} and @code{force(false)}.
|
||
YAP currently ignores these options.
|
||
|
||
@item absolute_file_name(+@var{Name},-@var{FullPath})
|
||
@findex absolute_file_name/2
|
||
@syindex absolute_file_name/2
|
||
@cnindex absolute_file_name/2
|
||
Give the path a full path @var{FullPath} Yap would use to consult a file
|
||
named @var{Name}. Unify @var{FullPath} with @code{user} if the file
|
||
name is @code{user}.
|
||
|
||
@item current_stream(@var{F},@var{M},@var{S})
|
||
@findex current_stream/3
|
||
@syindex current_stream/3
|
||
@cnindex current_stream/3
|
||
Defines the relation: The stream @var{S} is opened on the file @var{F}
|
||
in mode @var{M}. It might be used to obtain all open streams (by
|
||
backtracking) or to access the stream for a file @var{F} in mode
|
||
@var{M}, or to find properties for a stream @var{S}.
|
||
|
||
@item flush_output [ISO]
|
||
@findex flush_output/0
|
||
@syindex flush_output/0
|
||
@cnindex flush_output/0
|
||
Send all data in the output buffer to current output stream.
|
||
|
||
@item flush_output(+@var{S}) [ISO]
|
||
@findex flush_output/1
|
||
@syindex flush_output/1
|
||
@cnindex flush_output/1
|
||
Send all data in the output buffer to stream @var{S}.
|
||
|
||
@item set_input(+@var{S})
|
||
@findex set_input/1
|
||
@syindex set_input/1
|
||
@cnindex set_input/1
|
||
Set stream @var{S} as the current input stream. Predicates like @code{read/1}
|
||
and @code{get/1} will start using stream @var{S}.
|
||
|
||
@item set_output(+@var{S})
|
||
@findex set_output/1
|
||
@syindex set_output/1
|
||
@cnindex set_output/1
|
||
Set stream @var{S} as the current output stream. Predicates like
|
||
@code{write/1} and @code{put/1} will start using stream @var{S}.
|
||
|
||
@item stream_select(+@var{STREAMS},+@var{TIMEOUT},-@var{READSTREAMS})
|
||
@findex stream_select/3
|
||
@syindex stream_select/3
|
||
@cnindex stream_select/3
|
||
Given a list of open @var{STREAMS} openeded in read mode and a @var{TIMEOUT}
|
||
return a list of streams who are now available for reading.
|
||
|
||
If the @var{TIMEOUT} is instantiated to @code{off},
|
||
@code{stream_select/3} will wait indefinitely for a stream to become
|
||
open. Otherwise the timeout must be of the form @code{SECS:USECS} where
|
||
@code{SECS} is an integer gives the number of seconds to wait for a timeout
|
||
and @code{USECS} adds the number of micro-seconds.
|
||
|
||
This built-in is only defined if the system call @code{select} is
|
||
available in the system.
|
||
|
||
@item current_input(-@var{S}) [ISO]
|
||
@findex current_input/1
|
||
@syindex current_input/1
|
||
@cnindex current_input/1
|
||
Unify @var{S} with the current input stream.
|
||
|
||
@item current_output(-@var{S}) [ISO]
|
||
@findex current_output/1
|
||
@syindex current_output/1
|
||
@cnindex current_output/1
|
||
Unify @var{S} with the current output stream.
|
||
|
||
@item at_end_of_stream [ISO]
|
||
@findex at_end_of_stream/0
|
||
@syindex at_end_of_stream/0
|
||
@cnindex at_end_of_stream/0
|
||
Succeed if the current stream has stream position end-of-stream or
|
||
past-end-of-stream.
|
||
|
||
@item at_end_of_stream(+@var{S}) [ISO]
|
||
@findex at_end_of_stream/1
|
||
@syindex at_end_of_stream/1
|
||
@cnindex at_end_of_stream/1
|
||
Succeed if the stream @var{S} has stream position end-of-stream or
|
||
past-end-of-stream. Note that @var{S} must be a readable stream.
|
||
|
||
@item set_stream_position(+@var{S}, +@var{POS}) [ISO]
|
||
@findex set_stream_position/2
|
||
@syindex set_stream_position/2
|
||
@cnindex set_stream_position/2
|
||
Given a stream position @var{POS} for a stream @var{S}, set the current
|
||
stream position for @var{S} to be @var{POS}.
|
||
|
||
@item stream_property(?@var{Stream},?@var{Prop}) [ISO]
|
||
@findex stream_property/2
|
||
@snindex stream_property/2
|
||
@cnindex stream_property/2
|
||
|
||
Obtain the properties for the open streams. If the first argument is
|
||
unbound, the procedure will backtrack through all open
|
||
streams. Otherwise, the first argument must be a stream term (you may
|
||
use @code{current_stream} to obtain a current stream given a file name).
|
||
|
||
The following properties are recognized:
|
||
|
||
@table @code
|
||
|
||
@item file_name(@var{P})
|
||
An atom giving the file name for the current stream. The file names are
|
||
@code{user_input}, @code{user_output}, and @code{user_error} for the
|
||
standard streams.
|
||
|
||
@item mode(@var{P})
|
||
The mode used to open the file. It may be one of @code{append},
|
||
@code{read}, or @code{write}.
|
||
|
||
@item input
|
||
The stream is readable.
|
||
|
||
@item output
|
||
The stream is writable.
|
||
|
||
@item alias(@var{A})
|
||
ISO-Prolog primitive for stream aliases. @t{Yap} returns one of the
|
||
existing aliases for the stream.
|
||
|
||
@item position(@var{P})
|
||
A term describing the position in the stream.
|
||
|
||
@item end_of_stream(@var{E})
|
||
Whether the stream is @code{at} the end of stream, or it has found the
|
||
end of stream and is @code{past}, or whether it has @code{not} yet
|
||
reached the end of stream.
|
||
|
||
@item eof_action(@var{A})
|
||
The action to take when trying to read after reaching the end of
|
||
stream. The action may be one of @code{error}, generate an error,
|
||
@code{eof_code}, return character code @code{-1}, or @code{reset} the
|
||
stream.
|
||
|
||
@item reposition(@var{B})
|
||
Whether the stream can be repositioned or not, that is, whether it is
|
||
seekable.
|
||
|
||
@item type(@var{T})
|
||
Whether the stream is a @code{text} stream or a @code{binary} stream.
|
||
|
||
@end table
|
||
|
||
@end table
|
||
|
||
@node C-Prolog File Handling, I/O of Terms, Streams and Files, I/O
|
||
@subsection Handling Streams and Files
|
||
|
||
@table @code
|
||
|
||
@item tell(+@var{S})
|
||
@findex tell/1
|
||
@syindex tell/1
|
||
@cyindex tell/1
|
||
If @var{S} is a currently opened stream for output, it becomes the
|
||
current output stream. If @var{S} is an atom it is taken to be a
|
||
filename. If there is no output stream currently associated with it,
|
||
then it is opened for output, and the new output stream created becomes
|
||
the current output stream. If it is not possible to open the file, an
|
||
error occurs. If there is a single opened output stream currently
|
||
associated with the file, then it becomes the current output stream; if
|
||
there are more than one in that condition, one of them is chosen.
|
||
|
||
Whenever @var{S} is a stream not currently opened for output, an error
|
||
may be reported, depending on the state of the file_errors flag. The
|
||
predicate just fails, if @var{S} is neither a stream nor an atom.
|
||
|
||
@item telling(-@var{S})
|
||
@findex telling/1
|
||
@syindex telling/1
|
||
@cyindex telling/1
|
||
The current output stream is unified with @var{S}.
|
||
|
||
@item told
|
||
@findex told/0
|
||
@syindex told/0
|
||
@cyindex told/0
|
||
Closes the current output stream, and the user's terminal becomes again
|
||
the current output stream. It is important to remember to close streams
|
||
after having finished using them, as the maximum number of
|
||
simultaneously opened streams is 17.
|
||
|
||
@item see(+@var{S})
|
||
@findex see/1
|
||
@syindex see/1
|
||
@cyindex see/1
|
||
If @var{S} is a currently opened input stream then it is assumed to be
|
||
the current input stream. If @var{S} is an atom it is taken as a
|
||
filename. If there is no input stream currently associated with it, then
|
||
it is opened for input, and the new input stream thus created becomes
|
||
the current input stream. If it is not possible to open the file, an
|
||
error occurs. If there is a single opened input stream currently
|
||
associated with the file, it becomes the current input stream; if there
|
||
are more than one in that condition, then one of them is chosen.
|
||
|
||
When @var{S} is a stream not currently opened for input, an error may be
|
||
reported, depending on the state of the @code{file_errors} flag. If
|
||
@var{S} is neither a stream nor an atom the predicates just fails.
|
||
|
||
@item seeing(-@var{S})
|
||
@findex seeing/1
|
||
@syindex seeing/1
|
||
@cyindex seeing/1
|
||
The current input stream is unified with @var{S}.
|
||
|
||
@item seen
|
||
@findex seen/0
|
||
@syindex seen/0
|
||
@cyindex seen/0
|
||
Closes the current input stream (see 6.7.).
|
||
|
||
@end table
|
||
|
||
@node I/O of Terms, I/O of Characters, C-Prolog File Handling, I/O
|
||
@subsection Handling Input/Output of Terms
|
||
|
||
@table @code
|
||
|
||
@item read(-@var{T}) [ISO]
|
||
@findex read/1
|
||
@syindex read/1
|
||
@cyindex read/1
|
||
Reads the next term from the current input stream, and unifies it with
|
||
@var{T}. The term must be followed by a dot ('.') and any blank-character
|
||
as previously defined. The syntax of the term must match the current
|
||
declarations for operators (see op). If the end-of-stream is reached,
|
||
@var{T} is unified with the atom @code{end_of_file}. Further reads from of
|
||
the same stream may cause an error failure (see @code{open/3}).
|
||
|
||
@item read_term(-@var{T},+@var{Options}) [ISO]
|
||
@findex read_term/2
|
||
@saindex read_term/2
|
||
@cnindex read_term/2
|
||
Reads term @var{T} from the current input stream with execution
|
||
controlled by the following options:
|
||
|
||
@table @code
|
||
|
||
@item singletons(-@var{Names})
|
||
@findex singletons/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the form @var{Name=Var}, where
|
||
@var{Name} is the name of a non-anonymous singleton variable in the
|
||
original term, and @code{Var} is the variable's representation in
|
||
YAP.
|
||
|
||
@item syntax_errors(+@var{Val})
|
||
@findex syntax_errors/1 (read_term/2 option)
|
||
Control action to be taken after syntax errors. See @code{yap_flag/2}
|
||
for detailed information.
|
||
|
||
@item variable_names(-@var{Names})
|
||
@findex variable_names/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the form @var{Name=Var}, where @var{Name} is
|
||
the name of a non-anonymous variable in the original term, and @var{Var}
|
||
is the variable's representation in YAP.
|
||
|
||
@item variables(-@var{Names})
|
||
@findex variables/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the variables in term @var{T}.
|
||
|
||
@end table
|
||
|
||
@item char_conversion(+@var{IN},+@var{OUT}) [ISO]
|
||
@findex char_conversion/2
|
||
@syindex char_conversion/2
|
||
@cnindex char_conversion/2
|
||
While reading terms convert unquoted occurrences of the character
|
||
@var{IN} to the character @var{OUT}. Both @var{IN} and @var{OUT} must be
|
||
bound to single characters atoms.
|
||
|
||
Character conversion only works if the flag @code{char_conversion} is
|
||
on. This is default in the @code{iso} and @code{sicstus} language
|
||
modes. As an example, character conversion can be used for instance to
|
||
convert characters from the ISO-LATIN-1 character set to ASCII.
|
||
|
||
If @var{IN} is the same character as @var{OUT}, @code{char_conversion/2}
|
||
will remove this conversion from the table.
|
||
|
||
@item current_char_conversion(?@var{IN},?@var{OUT}) [ISO]
|
||
@findex current_char_conversion/2
|
||
@syindex current_char_conversion/2
|
||
@cnindex current_char_conversion/2
|
||
If @var{IN} is unbound give all current character
|
||
translations. Otherwise, give the translation for @var{IN}, if one
|
||
exists.
|
||
|
||
@item write(@var{T}) [ISO]
|
||
@findex write/1
|
||
@syindex write/1
|
||
@cyindex write/1
|
||
The term @var{T} is written to the current output stream according to
|
||
the operator declarations in force.
|
||
|
||
@item display(+@var{T})
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cyindex display/1
|
||
Displays term @var{T} on the current output stream. All Prolog terms are
|
||
written in standard parenthesized prefix notation.
|
||
|
||
@item write_canonical(+@var{T}) [ISO]
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cnindex display/1
|
||
Displays term @var{T} on the current output stream. Atoms are quoted
|
||
when necessary, and operators are ignored, that is, the term is written
|
||
in standard parenthesized prefix notation.
|
||
|
||
@item write_term(+@var{T}, +@var{Opts}) [ISO]
|
||
@findex write_term/2
|
||
@syindex write_term/2
|
||
@cnindex write_term/2
|
||
Displays term @var{T} on the current output stream, according to the
|
||
following options:
|
||
|
||
@table @code
|
||
@item quoted(+@var{Bool})
|
||
If @code{true}, quote atoms if this would be necessary for the atom to
|
||
be recognized as an atom by YAP's parser. The default value is
|
||
@code{false}.
|
||
|
||
@item ignore_ops(+@var{Bool})
|
||
If @code{true}, ignore operator declarations when writing the term. The
|
||
default value is @code{false}.
|
||
|
||
@item numbervars(+@var{Bool})
|
||
If @code{true}, output terms of the form
|
||
@code{'$VAR'(N)}, where @var{N} is an integer, as a sequence of capital
|
||
letters. The default value is @code{false}.
|
||
|
||
@item portrayed(+@var{Bool})
|
||
If @code{true}, use @t{portray/1} to portray bound terms. The default
|
||
value is @code{false}.
|
||
|
||
@item max_depth(+@var{Depth})
|
||
If @code{Depth} is a positive integer, use @t{Depth} as
|
||
the maximum depth to portray a term. The default is @code{0}, that is,
|
||
unlimited depth.
|
||
|
||
@end table
|
||
|
||
@item writeq(@var{T}) [ISO]
|
||
@findex writeq/1
|
||
@syindex writeq/1
|
||
@cyindex writeq/1
|
||
Writes the term @var{T}, quoting names to make the result acceptable to
|
||
the predicate 'read' whenever necessary.
|
||
|
||
@item print(@var{T})
|
||
@findex print/1
|
||
@syindex print/1
|
||
@cyindex print/1
|
||
Prints the term @var{T} to the current output stream using @code{write/1}
|
||
unless T is bound and a call to the user-defined predicate
|
||
@code{portray/1} succeeds. To do pretty printing of terms the user should
|
||
define suitable clauses for @code{portray/1} and use @code{print/1}.
|
||
|
||
@item format(+@var{T},+@var{L})
|
||
@findex format/2
|
||
@saindex format/2
|
||
@cnindex format/2
|
||
Print formatted output to the current output stream. The arguments in
|
||
list @var{L} are output according to the string or atom @var{T}.
|
||
|
||
A control sequence is introduced by a @code{w}. The following control
|
||
sequences are available in YAP:
|
||
|
||
@table @code
|
||
|
||
@item '~~'
|
||
Print a single tilde.
|
||
|
||
@item '~a'
|
||
The next argument must be an atom, that will be printed as if by @code{write}.
|
||
|
||
@item '~Nc'
|
||
The next argument must be an integer, that will be printed as a
|
||
character code. The number @var{N} is the number of times to print the
|
||
character (default 1).
|
||
|
||
@item '~Ne'
|
||
@itemx '~NE'
|
||
@itemx '~Nf'
|
||
@itemx '~Ng'
|
||
@itemx '~NG'
|
||
The next argument must be a floating point number. The float @var{F}, the number
|
||
@var{N} and the control code @code{c} will be passed to @code{printf} as:
|
||
|
||
@example
|
||
printf("%s.Nc", F)
|
||
@end example
|
||
|
||
As an example:
|
||
|
||
@example
|
||
?- format("~8e, ~8E, ~8f, ~8g, ~8G~w",
|
||
[3.14,3.14,3.14,3.14,3.14,3.14]).
|
||
3.140000e+00, 3.140000E+00, 3.140000, 3.14, 3.143.14
|
||
@end example
|
||
|
||
@item '~Nd'
|
||
The next argument must be an integer, and @var{N} is the number of digits
|
||
after the decimal point. If @var{N} is @code{0} no decimal points will be
|
||
printed. The default is @var{N = 0}.
|
||
|
||
@example
|
||
?- format("~2d, ~d",[15000, 15000]).
|
||
150.00, 15000
|
||
@end example
|
||
|
||
@item '~ND'
|
||
Identical to @code{'~Nd'}, except that commas are used to separate groups
|
||
of three digits.
|
||
|
||
@example
|
||
?- format("~2D, ~D",[150000, 150000]).
|
||
1,500.00, 150,000
|
||
@end example
|
||
|
||
@item '~i'
|
||
Ignore the next argument in the list of arguments:
|
||
|
||
@example
|
||
?- format('The ~i met the boregrove',[mimsy]).
|
||
The met the boregrove
|
||
@end example
|
||
|
||
@item '~k'
|
||
Print the next argument with @code{write_canonical}:
|
||
|
||
@example
|
||
?- format("Good night ~k",a+[1,2]).
|
||
Good night +(a,[1,2])
|
||
@end example
|
||
|
||
@item '~Nn'
|
||
Print @var{N} newlines (where @var{N} defaults to 1).
|
||
|
||
@item '~NN'
|
||
Print @var{N} newlines if at the beginning of the line (where @var{N}
|
||
defaults to 1).
|
||
|
||
@item '~Nr'
|
||
The next argument must be an integer, and @var{N} is interpreted as a
|
||
radix, such that @code{2 <= N <= 36} (the default is 8).
|
||
|
||
@example
|
||
?- format("~2r, 0x~16r, ~r",
|
||
[150000, 150000, 150000]).
|
||
100100100111110000, 0x249f0, 444760
|
||
@end example
|
||
|
||
@noindent
|
||
Note that the letters @code{a-z} denote digits larger than 9.
|
||
|
||
@item '~NR'
|
||
Similar to '~NR'. The next argument must be an integer, and @var{N} is
|
||
interpreted as a radix, such that @code{2 <= N <= 36} (the default is 8).
|
||
|
||
@example
|
||
?- format("~2r, 0x~16r, ~r",
|
||
[150000, 150000, 150000]).
|
||
100100100111110000, 0x249F0, 444760
|
||
@end example
|
||
|
||
@noindent
|
||
The only difference is that letters @code{A-Z} denote digits larger than 9.
|
||
|
||
@item '~p'
|
||
Print the next argument with @code{print/1}:
|
||
|
||
@example
|
||
?- format("Good night ~p",a+[1,2]).
|
||
Good night a+[1,2]
|
||
@end example
|
||
|
||
@item '~q'
|
||
Print the next argument with @code{writeq/1}:
|
||
|
||
@example
|
||
?- format("Good night ~q",'Hello'+[1,2]).
|
||
Good night 'Hello'+[1,2]
|
||
@end example
|
||
|
||
@item '~Ns'
|
||
The next argument must be a list of character codes. The system then
|
||
outputs their representation as a string, where @var{N} is the maximum
|
||
number of characters for the string (@var{N} defaults to the length of the
|
||
string).
|
||
|
||
@example
|
||
?- format("The ~s are ~4s",["woods","lovely"]).
|
||
The woods are love
|
||
@end example
|
||
|
||
@item '~w'
|
||
Print the next argument with @code{write/1}:
|
||
|
||
@example
|
||
?- format("Good night ~w",'Hello'+[1,2]).
|
||
Good night Hello+[1,2]
|
||
@end example
|
||
|
||
@end table
|
||
The number of arguments, @code{N}, may be given as an integer, or it
|
||
may be given as an extra argument. The next example shows a small
|
||
procedure to write a variable number of @code{a} characters:
|
||
|
||
@example
|
||
write_many_as(N) :-
|
||
format("~*c",[N,0'a]).
|
||
@end example
|
||
|
||
The @code{format/2} built-in also allows for formatted output. One can
|
||
specify column boundaries and fill the intermediate space by a padding
|
||
character:
|
||
|
||
@table @code
|
||
@item '~N|'
|
||
Set a column boundary at position @var{N}, where @var{N} defaults to the
|
||
current position.
|
||
|
||
@item '~N+'
|
||
Set a column boundary at @var{N} characters past the current position, where
|
||
@var{N} defaults to @code{8}.
|
||
|
||
|
||
@item '~Nt'
|
||
Set padding for a column, where @var{N} is the fill code (default is
|
||
@key{SPC}).
|
||
|
||
@end table
|
||
|
||
The next example shows how to align columns and padding. We first show
|
||
left-alignment:
|
||
|
||
@example
|
||
|
||
@code{
|
||
?- format("~n*Hello~16+*~n",[]).
|
||
*Hello *
|
||
}
|
||
@end example
|
||
|
||
Note that we reserve 16 characters for the column.
|
||
|
||
The following example shows how to do right-alignment:
|
||
|
||
|
||
@example
|
||
@code{
|
||
?- format("*~tHello~16+*~n",[]).
|
||
* Hello*
|
||
}
|
||
|
||
@end example
|
||
|
||
|
||
The @code{~t} escape sequence forces filling before @code{Hello}.
|
||
|
||
We next show how to do centering:
|
||
|
||
@example
|
||
@code{
|
||
?- format("*~tHello~t~16+*~n",[]).
|
||
* Hello *
|
||
}
|
||
@end example
|
||
|
||
|
||
The two @code{~t} escape sequence force filling both before and after
|
||
@code{Hello}. Space is then evenly divided between the right and the
|
||
left sides.
|
||
|
||
@item format(+@var{S},+@var{T},+@var{L})
|
||
@findex format/3
|
||
@saindex format/3
|
||
@cnindex format/3
|
||
Print formatted output to stream @var{S}.
|
||
|
||
|
||
@end table
|
||
|
||
@node I/O of Characters, I/O for Streams, I/O of Terms, I/O
|
||
@subsection Handling Input/Output of Characters
|
||
|
||
@table @code
|
||
|
||
@item put(+@var{N})
|
||
@findex put/1
|
||
@syindex put/1
|
||
@cyindex put/1
|
||
Outputs to the current output stream the character whose ASCII code is
|
||
@var{N}. The character @var{N} must be a legal ASCII character code, an
|
||
expression yielding such a code, or a list in which case only the first
|
||
element is used.
|
||
|
||
@item put_byte(+@var{N}) [ISO]
|
||
@findex put_byte/1
|
||
@snindex put_byte/1
|
||
@cnindex put_byte/1
|
||
Outputs to the current output stream the character whose code is
|
||
@var{N}. The current output stream must be a binary stream.
|
||
|
||
@item put_char(+@var{N}) [ISO]
|
||
@findex put_char/1
|
||
@snindex put_char/1
|
||
@cnindex put_char/1
|
||
Outputs to the current output stream the character who is used to build
|
||
the representation of atom @code{A}. The current output stream must be a
|
||
text stream.
|
||
|
||
@item put_code(+@var{N}) [ISO]
|
||
@findex put_code/1
|
||
@snindex put_code/1
|
||
@cnindex put_code/1
|
||
Outputs to the current output stream the character whose ASCII code is
|
||
@var{N}. The current output stream must be a text stream. The character
|
||
@var{N} must be a legal ASCII character code, an expression yielding such
|
||
a code, or a list in which case only the first element is used.
|
||
|
||
@item get(-@var{C})
|
||
@findex get/1
|
||
@syindex get/1
|
||
@cyindex get/1
|
||
The next non-blank character from the current input stream is unified
|
||
with @var{C}. Blank characters are the ones whose ASCII codes are not
|
||
greater than 32. If there are no more non-blank characters in the
|
||
stream, @var{C} is unified with -1. If @code{end_of_stream} has already
|
||
been reached in the previous reading, this call will give an error message.
|
||
|
||
@item get0(-@var{C})
|
||
@findex get0/1
|
||
@syindex get0/1
|
||
@cyindex get0/1
|
||
The next character from the current input stream is consumed, and then
|
||
unified with @var{C}. There are no restrictions on the possible
|
||
values of the ASCII code for the character, but the character will be
|
||
internally converted by YAP.
|
||
|
||
@item get_byte(-@var{C}) [ISO]
|
||
@findex get_byte/1
|
||
@snindex get_byte/1
|
||
@cnindex get_byte/1
|
||
If @var{C} is unbound, or is a character code, and the current stream is a
|
||
binary stream, read the next byte from the current stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item get_char(-@var{C}) [ISO]
|
||
@findex get_char/1
|
||
@snindex get_char/1
|
||
@cnindex get_char/1
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its atom representation with @var{C}.
|
||
|
||
@item get_code(-@var{C}) [ISO]
|
||
@findex get_code/1
|
||
@snindex get_code/1
|
||
@cnindex get_code/1
|
||
If @var{C} is unbound, or is the code for a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its code with @var{C}.
|
||
|
||
@item peek_byte(-@var{C}) [ISO]
|
||
@findex peek_byte/1
|
||
@snindex peek_byte/1
|
||
@cnindex peek_byte/1
|
||
If @var{C} is unbound, or is a character code, and the current stream is a
|
||
binary stream, read the next byte from the current stream and unify its
|
||
code with @var{C}, while leaving the current stream position unaltered.
|
||
|
||
@item peek_char(-@var{C}) [ISO]
|
||
@findex peek_char/1
|
||
@syindex peek_char/1
|
||
@cnindex peek_char/1
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its atom representation with @var{C}, while
|
||
leaving the current stream position unaltered.
|
||
|
||
@item peek_code(-@var{C}) [ISO]
|
||
@findex peek_code/1
|
||
@snindex peek_code/1
|
||
@cnindex peek_code/1
|
||
If @var{C} is unbound, or is the code for a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its code with @var{C}, while
|
||
leaving the current stream position unaltered.
|
||
|
||
@item skip(+@var{N})
|
||
@findex skip/1
|
||
@syindex skip/1
|
||
@cyindex skip/1
|
||
Skips input characters until the next occurrence of the character with
|
||
ASCII code @var{N}. The argument to this predicate can take the same forms
|
||
as those for @code{put} (see 6.11).
|
||
|
||
@item tab(+@var{N})
|
||
@findex tab/1
|
||
@syindex tab/1
|
||
@cyindex tab/1
|
||
Outputs @var{N} spaces to the current output stream.
|
||
|
||
@item nl [ISO]
|
||
@findex nl/0
|
||
@syindex nl/0
|
||
@cyindex nl/0
|
||
Outputs a new line to the current output stream.
|
||
|
||
@end table
|
||
|
||
@node I/O for Streams, C-Prolog to Terminal, I/O of Characters, I/O
|
||
@subsection Input/Output Predicates applied to Streams
|
||
|
||
@table @code
|
||
|
||
@item read(+@var{S},-@var{T}) [ISO]
|
||
@findex read/2
|
||
@syindex read/2
|
||
@cnindex read/2
|
||
Reads term @var{T} from the stream @var{S} instead of from the current input
|
||
stream.
|
||
|
||
@item read_term(+@var{S},-@var{T},+@var{Options}) [ISO]
|
||
@findex read_term/3
|
||
@saindex read_term/3
|
||
@cnindex read_term/3
|
||
Reads term @var{T} from stream @var{S} with execution controlled by the
|
||
same options as @code{read_term/2}.
|
||
|
||
@item write(+@var{S},@var{T}) [ISO]
|
||
@findex write/2
|
||
@syindex write/2
|
||
@cnindex write/2
|
||
Writes term @var{T} to stream @var{S} instead of to the current output
|
||
stream.
|
||
|
||
@item write_canonical(+@var{S},+@var{T}) [ISO]
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cnindex display/1
|
||
Displays term @var{T} on the stream @var{S}. Atoms are quoted when
|
||
necessary, and operators are ignored.
|
||
|
||
@item write_term(+@var{S}, +@var{T}, +@var{Opts}) [ISO]
|
||
@findex write_term/3
|
||
@syindex write_term/3
|
||
@cnindex write_term/3
|
||
Displays term @var{T} on the current output stream, according to the same
|
||
options used by @code{write_term/3}.
|
||
|
||
@item writeq(+@var{S},@var{T}) [ISO]
|
||
@findex writeq/2
|
||
@syindex writeq/2
|
||
@cnindex writeq/2
|
||
As @code{writeq/1}, but the output is sent to the stream @var{S}.
|
||
|
||
@item display(+@var{S},@var{T})
|
||
@findex display/2
|
||
@syindex display/2
|
||
@cnindex display/2
|
||
Like @code{display/1}, but using stream @var{S} to display the term.
|
||
|
||
@item print(+@var{S},@var{T})
|
||
@findex print/2
|
||
@syindex print/2
|
||
@cnindex print/2
|
||
Prints term @var{T} to the stream @var{S} instead of to the current output
|
||
stream.
|
||
|
||
@item put(+@var{S},+@var{N})
|
||
@findex put/2
|
||
@syindex put/2
|
||
@cnindex put/2
|
||
As @code{put(N)}, but to stream @var{S}.
|
||
|
||
@item put_byte(+@var{S},+@var{N}) [ISO]
|
||
@findex put_byte/2
|
||
@snindex put_byte/2
|
||
@cnindex put_byte/2
|
||
As @code{put_byte(N)}, but to binary stream @var{S}.
|
||
|
||
@item put_char(+@var{S},+@var{A}) [ISO]
|
||
@findex put_char/2
|
||
@snindex put_char/2
|
||
@cnindex put_char/2
|
||
As @code{put_char(A)}, but to text stream @var{S}.
|
||
|
||
@item put_code(+@var{S},+@var{N}) [ISO]
|
||
@findex put_code/2
|
||
@snindex put_code/2
|
||
@cnindex put_code/2
|
||
As @code{put_code(N)}, but to text stream @var{S}.
|
||
|
||
@item get(+@var{S},-@var{C})
|
||
@findex get/2
|
||
@syindex get/2
|
||
@cnindex get/2
|
||
The same as @code{get(C)}, but from stream @var{S}.
|
||
|
||
@item get0(+@var{S},-@var{C})
|
||
@findex get0/2
|
||
@syindex get0/2
|
||
@cnindex get0/2
|
||
The same as @code{get0(C)}, but from stream @var{S}.
|
||
|
||
@item get_byte(+@var{S},-@var{C}) [ISO]
|
||
@findex get_byte/2
|
||
@snindex get_byte/2
|
||
@cnindex get_byte/2
|
||
If @var{C} is unbound, or is a character code, and the stream @var{S} is a
|
||
binary stream, read the next byte from that stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item get_char(+@var{S},-@var{C}) [ISO]
|
||
@findex get_char/2
|
||
@snindex get_char/2
|
||
@cnindex get_char/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}.
|
||
|
||
@item get_code(+@var{S},-@var{C}) [ISO]
|
||
@findex get_code/2
|
||
@snindex get_code/2
|
||
@cnindex get_code/2
|
||
If @var{C} is unbound, or is a character code, and the stream @var{S} is a
|
||
text stream, read the next character from that stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item peek_byte(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_byte/2
|
||
@snindex peek_byte/2
|
||
@cnindex peek_byte/2
|
||
If @var{C} is unbound, or is a character code, and @var{S} is a binary
|
||
stream, read the next byte from the current stream and unify its code
|
||
with @var{C}, while leaving the current stream position unaltered.
|
||
|
||
@item peek_char(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_char/2
|
||
@snindex peek_char/2
|
||
@cnindex peek_char/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}, while leaving
|
||
the current stream position unaltered.
|
||
|
||
@item peek_code(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_code/2
|
||
@snindex peek_code/2
|
||
@cnindex peek_code/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}, while leaving
|
||
the current stream position unaltered.
|
||
|
||
@item skip(+@var{S},-@var{C})
|
||
@findex skip/2
|
||
@syindex skip/2
|
||
@cnindex skip/2
|
||
Like @code{skip/1}, but using stream @var{S} instead of the current
|
||
input stream.
|
||
|
||
@item tab(+@var{S},+@var{N})
|
||
@findex tab/2
|
||
@syindex tab/2
|
||
@cnindex tab/2
|
||
The same as @code{tab/1}, but using stream @var{S}.
|
||
|
||
@item nl(+@var{S})
|
||
@findex nl/1
|
||
@syindex nl/1
|
||
@cnindex nl/1
|
||
Outputs a new line to stream @var{S}.
|
||
|
||
@end table
|
||
|
||
@node C-Prolog to Terminal, I/O Control, I/O for Streams, I/O
|
||
@subsection Compatible C-Prolog predicates for Terminal I/O
|
||
|
||
@table @code
|
||
|
||
@item ttyput(+@var{N})
|
||
@findex ttyput/1
|
||
@syindex ttyput/1
|
||
@cnindex ttyput/1
|
||
As @code{put(N)} but always to @code{user_output}.
|
||
|
||
@item ttyget(-@var{C})
|
||
@findex ttyget/1
|
||
@syindex ttyget/1
|
||
@cnindex ttyget/1
|
||
The same as @code{get(C)}, but from stream @code{user_input}.
|
||
|
||
@item ttyget0(-@var{C})
|
||
@findex ttyget0/1
|
||
@syindex ttyget0/1
|
||
@cnindex ttyget0/1
|
||
The same as @code{get0(C)}, but from stream @code{user_input}.
|
||
|
||
@item ttyskip(-@var{C})
|
||
@findex ttyskip/1
|
||
@syindex ttyskip/1
|
||
@cnindex ttyskip/1
|
||
Like @code{skip/1}, but always using stream @code{user_input}.
|
||
stream.
|
||
|
||
@item ttytab(+@var{N})
|
||
@findex ttytab/1
|
||
@syindex ttytab/1
|
||
@cnindex ttytab/1
|
||
The same as @code{tab/1}, but using stream @code{user_output}.
|
||
|
||
@item ttynl
|
||
@findex ttynl/0
|
||
@syindex ttynl/0
|
||
@cnindex ttynl/0
|
||
Outputs a new line to stream @code{user_output}.
|
||
|
||
@end table
|
||
|
||
@node I/O Control, Sockets, C-Prolog to Terminal, I/O
|
||
@subsection Controlling Input/Output
|
||
|
||
@table @code
|
||
|
||
@item exists(+@var{F})
|
||
@findex exists/1
|
||
@snindex exists/1
|
||
@cyindex exists/1
|
||
Checks if file @var{F} exists in the current directory.
|
||
|
||
@item nofileerrors
|
||
@findex nofileerrors/0
|
||
@syindex nofileerrors/0
|
||
@cyindex nofileerrors/0
|
||
Switches off the file_errors flag, so that the predicates @code{see/1},
|
||
@code{tell/1}, @code{open/3} and @code{close/1} just fail, instead of producing
|
||
an error message and aborting whenever the specified file cannot be
|
||
opened or closed.
|
||
|
||
@item fileerrors
|
||
@findex fileerrors/0
|
||
@syindex fileerrors/0
|
||
@cyindex fileerrors/0
|
||
Switches on the file_errors flag so that in certain error conditions
|
||
I/O predicates will produce an appropriated message and abort.
|
||
|
||
@item write_depth(@var{T},@var{L},@var{A})
|
||
@findex write_depth/3
|
||
@snindex write_depth/3
|
||
@cnindex write_depth/3
|
||
Unifies @var{T} with the value of the maximum depth of a term to be
|
||
written, @var{L} with the maximum length of a list to write, and @var{A}
|
||
with the maximum number of arguments of a compound term to write. The
|
||
setting will be used by @code{write/1} or @code{write/2}. The default
|
||
value for all arguments is 0, meaning unlimited depth and length.
|
||
|
||
@example
|
||
?- write_depth(3,5,5).
|
||
yes
|
||
?- write(a(b(c(d(e(f(g))))))).
|
||
a(b(c(....)))
|
||
yes
|
||
?- write([1,2,3,4,5,6,7,8]).
|
||
[1,2,3,4,5,...]
|
||
yes
|
||
?- write(a(1,2,3,4,5,6,7,8)).
|
||
a(1,2,3,4,5,...)
|
||
yes
|
||
@end example
|
||
|
||
@item write_depth(@var{T},@var{L})
|
||
@findex write_depth/2
|
||
@snindex write_depth/2
|
||
Same as @code{write_depth(@var{T},@var{L},_)}. Unifies @var{T} with the
|
||
value of the maximum depth of a term to be
|
||
written, and @var{L} with the maximum length of a list to write. The
|
||
setting will be used by @code{write/1} or @code{write/2}. The default
|
||
value for all arguments is 0, meaning unlimited depth and length.
|
||
|
||
@example
|
||
?- write_depth(3,5,5).
|
||
yes
|
||
?- write(a(b(c(d(e(f(g))))))).
|
||
a(b(c(....)))
|
||
yes
|
||
?- write([1,2,3,4,5,6,7,8]).
|
||
[1,2,3,4,5,...]
|
||
yes
|
||
@end example
|
||
|
||
@item always_prompt_user
|
||
@findex always_prompt_user/0
|
||
@snindex always_prompt_user/0
|
||
@cnindex always_prompt_user/0
|
||
Force the system to prompt the user even if the @code{user_input} stream
|
||
is not a terminal. This command is useful if you want to obtain
|
||
interactive control from a pipe or a socket.
|
||
|
||
@end table
|
||
|
||
@node Sockets, , I/O Control, I/O
|
||
@subsection Using Sockets From Yap
|
||
|
||
YAP includes a SICStus Prolog compatible socket interface. This
|
||
is a low level interface that provides direct access to the major socket
|
||
system calls. These calls can be used both to open a new connection in
|
||
the network or connect to a networked server. Socket connections are
|
||
described as read/write streams, and standard I/O built-ins can be used
|
||
to write on or read from sockets. The following calls are available:
|
||
|
||
@table @code
|
||
|
||
@item socket(+@var{DOMAIN},+@var{TYPE},+@var{PROTOCOL},-@var{SOCKET})
|
||
@findex socket/4
|
||
@syindex socket/4
|
||
@cnindex socket/4
|
||
Corresponds to the BSD system call @code{socket}. Create a socket for
|
||
domain @var{DOMAIN} of type @var{TYPE} and protocol
|
||
@var{PROTOCOL}. Both @var{DOMAIN} and @var{TYPE} should be atoms,
|
||
whereas @var{PROTOCOL} must be an integer. The new socket object is
|
||
accessible through a descriptor bound to the variable @var{SOCKET}.
|
||
|
||
The current implementation of YAP only accepts two socket
|
||
domains: @code{'AF_INET'} and @code{'AF_UNIX'}. Socket types depend on the
|
||
underlying operating system, but at least the following types are
|
||
supported: @code{'SOCK_STREAM'} and @code{'SOCK_DGRAM'}.
|
||
|
||
@item socket(+@var{DOMAIN},-@var{SOCKET})
|
||
@findex socket/2
|
||
@syindex socket/2
|
||
@cnindex socket/2
|
||
|
||
Call @code{socket/4} with @var{TYPE} bound to @code{'SOCK_STREAM'} and
|
||
@var{PROTOCOL} bound to @code{0}.
|
||
|
||
@item socket_close(+@var{SOCKET})
|
||
@findex socket_close/1
|
||
@syindex socket_close/1
|
||
@cnindex socket_close/1
|
||
|
||
Close socket @var{SOCKET}. Note that sockets used in
|
||
@code{socket_connect} (that is, client sockets) should not be closed with
|
||
@code{socket_close}, as they will be automatically closed when the
|
||
corresponding stream is closed with @code{close/1} or @code{close/2}.
|
||
|
||
@item socket_bind(+@var{SOCKET}, ?@var{PORT})
|
||
@findex socket_bind/2
|
||
@syindex socket_bind/2
|
||
@cnindex socket_bind/2
|
||
|
||
Interface to system call @code{bind}, as used for servers: bind socket
|
||
to a port. Port information depends on the domain:
|
||
@table @code
|
||
@item 'AF_UNIX'(+@var{FILENAME})
|
||
@item 'AF_FILE'(+@var{FILENAME})
|
||
use file name @var{FILENAME} for UNIX or local sockets.
|
||
|
||
@item 'AF_INET'(?@var{HOST},?PORT)
|
||
If @var{HOST} is bound to an atom, bind to host @var{HOST}, otherwise
|
||
if unbound bind to local host (@var{HOST} remains unbound). If port
|
||
@var{PORT} is bound to an integer, try to bind to the corresponding
|
||
port. If variable @var{PORT} is unbound allow operating systems to
|
||
choose a port number, which is unified with @var{PORT}.
|
||
|
||
@end table
|
||
|
||
@item socket_connect(+@var{SOCKET}, +@var{PORT}, -@var{STREAM})
|
||
@findex socket_connect/3
|
||
@syindex socket_connect/3
|
||
@cnindex socket_connect/3
|
||
|
||
Interface to system call @code{connect}, used for clients: connect
|
||
socket @var{SOCKET} to @var{PORT}. The connection results in the
|
||
read/write stream @var{STREAM}.
|
||
|
||
Port information depends on the domain:
|
||
@table @code
|
||
@item 'AF_UNIX'(+@var{FILENAME})
|
||
@item 'AF_FILE'(+@var{FILENAME})
|
||
connect to socket at file @var{FILENAME}.
|
||
|
||
@item 'AF_INET'(+@var{HOST},+@var{PORT})
|
||
Connect to socket at host @var{HOST} and port @var{PORT}.
|
||
@end table
|
||
|
||
@item socket_listen(+@var{SOCKET}, +@var{LENGTH})
|
||
@findex socket_listen/2
|
||
@syindex socket_listen/2
|
||
@cnindex socket_listen/2
|
||
Interface to system call @code{listen}, used for servers to indicate
|
||
willingness to wait for connections at socket @var{SOCKET}. The
|
||
integer @var{LENGTH} gives the queue limit for incoming connections,
|
||
and should be limited to @code{5} for portable applications. The socket
|
||
must be of type @code{SOCK_STREAM} or @code{SOCK_SEQPACKET}.
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{STREAM})
|
||
@findex socket_accept/2
|
||
@syindex socket_accept/2
|
||
@cnindex socket_accept/2
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{CLIENT}, -@var{STREAM})
|
||
@findex socket_accept/3
|
||
@syindex socket_accept/3
|
||
@cnindex socket_accept/3
|
||
Interface to system call @code{accept}, used for servers to wait for
|
||
connections at socket @var{SOCKET}. The stream descriptor @var{STREAM}
|
||
represents the resulting connection. If the socket belongs to the
|
||
domain @code{'AF_INET'}, @var{CLIENT} unifies with an atom containing
|
||
the IP address for the client in numbers and dots notation.
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{STREAM})
|
||
@findex socket_accept/2
|
||
@syindex socket_accept/2
|
||
@cnindex socket_accept/2
|
||
Accept a connection but do not return client information.
|
||
|
||
@item socket_buffering(+@var{SOCKET}, -@var{MODE}, -@var{OLD}, +@var{NEW})
|
||
@findex socket_buffering/4
|
||
@syindex socket_buffering/4
|
||
@cnindex socket_buffering/4
|
||
Set buffering for @var{SOCKET} in @code{read} or @code{write}
|
||
@var{MODE}. @var{OLD} is unified with the previous status, and @var{NEW}
|
||
receives the new status which may be one of @code{unbuf} or
|
||
@code{fullbuf}.
|
||
|
||
@item socket_select(+@var{SOCKETS}, -@var{NEWSTREAMS}, +@var{TIMEOUT}, +@var{STREAMS}, -@var{READSTREAMS})
|
||
@findex socket_select/5
|
||
@syindex socket_select/5
|
||
@cnindex socket_select/5
|
||
Interface to system call @code{select}, used for servers to wait for
|
||
connection requests or for data at sockets. The variable
|
||
@var{SOCKETS} is a list of form @var{KEY-SOCKET}, where @var{KEY} is
|
||
an user-defined identifier and @var{SOCKET} is a socket descriptor. The
|
||
variable @var{TIMEOUT} is either @code{off}, indicating execution will
|
||
wait until something is available, or of the form @var{SEC-USEC}, where
|
||
@var{SEC} and @var{USEC} give the seconds and microseconds before
|
||
@code{socket_select/5} returns. The variable @var{SOCKETS} is a list of
|
||
form @var{KEY-STREAM}, where @var{KEY} is an user-defined identifier
|
||
and @var{STREAM} is a stream descriptor
|
||
|
||
Execution of @code{socket_select/5} unifies @var{READSTREAMS} from
|
||
@var{STREAMS} with readable data, and @var{NEWSTREAMS} with a list of
|
||
the form @var{KEY-STREAM}, where @var{KEY} was the key for a socket
|
||
with pending data, and @var{STREAM} the stream descriptor resulting
|
||
from accepting the connection.
|
||
|
||
@item current_host(?@var{HOSTNAME})
|
||
Unify @var{HOSTNAME} with an atom representing the fully qualified
|
||
hostname for the current host. Also succeeds if @var{HOSTNAME} is bound
|
||
to the unqualified hostname.
|
||
|
||
@item hostname_address(?@var{HOSTNAME},?@var{IP_ADDRESS})
|
||
@var{HOSTNAME} is an host name and @var{IP_ADDRESS} its IP
|
||
address in number and dots notation.
|
||
|
||
|
||
@end table
|
||
|
||
@node Database, Sets, I/O, Top
|
||
@section Using the Clausal Data Base
|
||
|
||
Predicates in YAP may be dynamic or static. By default, when
|
||
consulting or reconsulting, predicates are assumed to be static:
|
||
execution is faster and the code will probably use less space.
|
||
Static predicates impose some restrictions: in general there can be no
|
||
addition or removal of clauses for a procedure if it is being used in the
|
||
current execution.
|
||
|
||
Dynamic predicates allow programmers to change the Clausal Data Base with
|
||
the same flexibility as in C-Prolog. With dynamic predicates it is
|
||
always possible to add or remove clauses during execution and the
|
||
semantics will be the same as for C-Prolog. But the programmer should be
|
||
aware of the fact that asserting or retracting are still expensive operations,
|
||
and therefore he should try to avoid them whenever possible.
|
||
|
||
@table @code
|
||
|
||
@item dynamic +@var{P}
|
||
@findex dynamic/1
|
||
@saindex dynamic/1
|
||
@cnindex dynamic/1
|
||
Declares predicate @var{P} or list of predicates [@var{P1},...,@var{Pn}]
|
||
as a dynamic predicate. @var{P} must be written in form:
|
||
@var{name/arity}.
|
||
|
||
@example
|
||
:- dynamic god/1.
|
||
@end example
|
||
|
||
@noindent
|
||
a more convenient form can be used:
|
||
|
||
@example
|
||
:- dynamic son/3, father/2, mother/2.
|
||
@end example
|
||
|
||
or, equivalently,
|
||
|
||
@example
|
||
:- dynamic [son/3, father/2, mother/2].
|
||
@end example
|
||
|
||
@noindent
|
||
Note:
|
||
|
||
a predicate is assumed to be dynamic when
|
||
asserted before being defined.
|
||
|
||
@item dynamic_predicate(+@var{P},+@var{Semantics})
|
||
@findex dynamic_predicate/2
|
||
@snindex dynamic_predicate/2
|
||
@cnindex dynamic_predicate/2
|
||
Declares predicate @var{P} or list of predicates [@var{P1},...,@var{Pn}]
|
||
as a dynamic predicate following either @code{logical} or
|
||
@code{immediate} semantics.
|
||
|
||
@menu
|
||
|
||
Subnodes of Database
|
||
* Modifying the Database:: Asserting and Retracting
|
||
* Looking at the Database:: Finding out what is in the Data Base
|
||
* Database References:: Using Data Base References
|
||
* Internal Database:: Yap's Internal Database
|
||
* BlackBoard:: Storing and Fetching Terms in the BlackBoard
|
||
|
||
@end menu
|
||
|
||
@end table
|
||
|
||
@node Modifying the Database, Looking at the Database, , Database
|
||
@subsection Modification of the Data Base
|
||
|
||
These predicates can be used either for static or for dynamic
|
||
predicates:
|
||
|
||
@table @code
|
||
|
||
@item assert(+@var{C})
|
||
@findex assert/1
|
||
@saindex assert/1
|
||
@caindex assert/1
|
||
Adds clause @var{C} to the program. If the predicate is undefined,
|
||
declare it as dynamic.
|
||
|
||
Most Prolog systems only allow asserting clauses for dynamic
|
||
predicates. This is also as specified in the ISO standard. YAP allows
|
||
asserting clauses for static predicates, as long as the predicate is not
|
||
in use and the language flag is @t{cprolog}. Note that this feature is
|
||
deprecated, if you want to assert clauses for static procedures you
|
||
should use @code{assert_static/1}.
|
||
|
||
@item asserta(+@var{C}) [ISO]
|
||
@findex asserta/1
|
||
@saindex asserta/1
|
||
@caindex asserta/1
|
||
Adds clause @var{C} to the beginning of the program. If the predicate is
|
||
undefined, declare it as dynamic.
|
||
|
||
@item assertz(+@var{C}) [ISO]
|
||
@findex assertz/1
|
||
@saindex assertz/1
|
||
@caindex assertz/1
|
||
Adds clause @var{C} to the end of the program. If the predicate is
|
||
undefined, declare it as dynamic.
|
||
|
||
Most Prolog systems only allow asserting clauses for dynamic
|
||
predicates. This is also as specified in the ISO standard. YAP allows
|
||
asserting clauses for static predicates. The current version of YAP
|
||
supports this feature, but this feature is deprecated and support may go
|
||
away in future versions.
|
||
|
||
@item abolish(+@var{PredSpec}) [ISO]
|
||
@findex abolish/1
|
||
@saindex abolish/1
|
||
@caindex abolish/1
|
||
Deletes the predicate given by @var{PredSpec} from the database. If
|
||
@var{PredSpec} is an unbound variable, delete all predicates for the
|
||
current module. The
|
||
specification must include the name and arity, and it may include module
|
||
information. Under @t{iso} language mode this built-in will only abolish
|
||
dynamic procedures. Under other modes it will abolish any procedures.
|
||
|
||
@item abolish(+@var{P},+@var{N})
|
||
@findex abolish/2
|
||
@saindex abolish/2
|
||
@caindex abolish/2
|
||
Deletes the predicate with name @var{P} and arity @var{N}. It will remove
|
||
both static and dynamic predicates.
|
||
|
||
@item assert_static(:@var{C})
|
||
@findex assert_static/1
|
||
@snindex assert_static/1
|
||
@cnindex assert_static/1
|
||
Adds clause @var{C} to a static procedure. Asserting a static clause
|
||
for a predicate while choice-points for the predicate are available has
|
||
undefined results.
|
||
|
||
@item asserta_static(:@var{C})
|
||
@findex asserta_static/1
|
||
@snindex asserta_static/1
|
||
@cnindex asserta_static/1
|
||
Adds clause @var{C} to the beginning of a static procedure.
|
||
|
||
@item assertz_static(:@var{C})
|
||
@findex assertz_static/1
|
||
@snindex assertz_static/1
|
||
@cnindex assertz_static/1
|
||
Adds clause @var{C} to the end of a static procedure. Asserting a
|
||
static clause for a predicate while choice-points for the predicate are
|
||
available has undefined results.
|
||
|
||
@end table
|
||
|
||
The following predicates can be used for dynamic predicates and for
|
||
static predicates, if source mode was on when they were compiled:
|
||
|
||
@table @code
|
||
|
||
@item clause(+@var{H},@var{B}) [ISO]
|
||
@findex clause/2
|
||
@saindex clause/2
|
||
@caindex clause/2
|
||
A clause whose head matches @var{H} is searched for in the
|
||
program. Its head and body are respectively unified with @var{H} and
|
||
@var{B}. If the clause is a unit clause, @var{B} is unified with
|
||
@var{true}.
|
||
|
||
This predicate is applicable to static procedures compiled with
|
||
@code{source} active, and to all dynamic procedures.
|
||
|
||
@item clause(+@var{H},@var{B},-@var{R})
|
||
@findex clause/3
|
||
@saindex clause/3
|
||
@caindex clause/3
|
||
The same as @code{clause/2}, plus @var{R} is unified with the
|
||
reference to the clause in the database. You can use @code{instance/2}
|
||
to access the reference's value. Note that you may not use
|
||
@code{erase/1} on the reference on static procedures.
|
||
|
||
@item nth_clause(+@var{H},@var{I},-@var{R})
|
||
@findex nth_clause/3
|
||
@saindex nth_clause/3
|
||
@caindex nth_clause/3
|
||
Find the @var{I}th clause in the predicate defining @var{H}, and give
|
||
a reference to the clause. Alternatively, if the reference @var{R} is
|
||
given the head @var{H} is unified with a description of the predicate
|
||
and @var{I} is bound to its position.
|
||
|
||
@end table
|
||
|
||
The following predicates can only be used for dynamic predicates:
|
||
|
||
@table @code
|
||
|
||
@item retract(+@var{C}) [ISO]
|
||
@findex retract/1
|
||
@saindex retract/1
|
||
@cnindex retract/1
|
||
Erases the first clause in the program that matches @var{C}. This
|
||
predicate may also be used for the static predicates that have been
|
||
compiled when the source mode was @code{on}. For more information on
|
||
@code{source/0} (@pxref{Setting the Compiler}).
|
||
|
||
@item retractall(+@var{G})
|
||
@findex retractall/1
|
||
@saindex retractall/1
|
||
@cnindex retractall/1
|
||
Retract all the clauses whose head matches the goal @var{G}. Goal
|
||
@var{G} must be a call to a dynamic predicate.
|
||
|
||
@end table
|
||
|
||
@node Looking at the Database, Database References, Modifying the Database, Database
|
||
@subsection Looking at the Data Base
|
||
|
||
@table @code
|
||
|
||
@item listing
|
||
@findex listing/0
|
||
@saindex listing/0
|
||
@caindex listing/0
|
||
Lists in the current output stream all the clauses for which source code
|
||
is available (these include all clauses for dynamic predicates and
|
||
clauses for static predicates compiled when source mode was @code{on}).
|
||
|
||
@item listing(+@var{P})
|
||
@findex listing/1
|
||
@syindex listing/1
|
||
@caindex listing/1
|
||
Lists predicate @var{P} if its source code is available.
|
||
|
||
@item portray_clause(+@var{C})
|
||
@findex portray_clause/1
|
||
@syindex portray_clause/1
|
||
@cnindex portray_clause/1
|
||
Write clause @var{C} as if written by @code{listing/0}.
|
||
|
||
@item portray_clause(+@var{S},+@var{C})
|
||
@findex portray_clause/2
|
||
@syindex portray_clause/2
|
||
@cnindex portray_clause/2
|
||
Write clause @var{C} on stream @var{S} as if written by @code{listing/0}.
|
||
|
||
@item current_atom(@var{A})
|
||
@findex current_atom/1
|
||
@syindex current_atom/1
|
||
@cyindex current_atom/1
|
||
Checks whether @var{A} is a currently defined atom. It is used to find all
|
||
currently defined atoms by backtracking.
|
||
|
||
@item current_predicate(@var{F}) [ISO]
|
||
@findex current_predicate/1
|
||
@syindex current_predicate/1
|
||
@cyindex current_predicate/1
|
||
@var{F} is the predicate indicator for a currently defined user or
|
||
library predicate. @var{F} is of the form @var{Na/Ar}, where the atom
|
||
@var{Na} is the name of the predicate, and @var{Ar} its arity.
|
||
|
||
@item current_predicate(@var{A},@var{P})
|
||
@findex current_predicate/2
|
||
@syindex current_predicate/2
|
||
@cnindex current_predicate/2
|
||
Defines the relation: @var{P} is a currently defined predicate whose
|
||
name is the atom @var{A}.
|
||
|
||
@item system_predicate(@var{A},@var{P})
|
||
@findex system_predicate/2
|
||
@syindex system_predicate/2
|
||
@cnindex system_predicate/2
|
||
Defines the relation: @var{P} is a built-in predicate whose name
|
||
is the atom @var{A}.
|
||
|
||
@item predicate_property(@var{P},@var{Prop})
|
||
@findex predicate_property/2
|
||
@saindex predicate_property/2
|
||
@cnindex predicate_property/2
|
||
For the predicates obeying the specification @var{P} unify @var{Prop}
|
||
with a property of @var{P}. These properties may be:
|
||
@table @code
|
||
@item built_in
|
||
true for built-in predicates,
|
||
@item dynamic
|
||
true if the predicate is dynamic
|
||
@item static
|
||
true if the predicate is static
|
||
@item meta_predicate(@var{M})
|
||
true if the predicate has a meta_predicate declaration @var{M}.
|
||
@item multifile
|
||
true if the predicate was declared to be multifile
|
||
@item imported_from(@var{Mod})
|
||
true if the predicate was imported from module @var{Mod}.
|
||
@item exported
|
||
true if the predicate is exported in the current module.
|
||
@item public
|
||
true if the predicate is public; note that all dynamic predicates are
|
||
public.
|
||
@item tabled
|
||
true if the predicate is tabled; note that only static predicates can
|
||
be tabled in YAP.
|
||
@item source
|
||
true if source for the predicate is available.
|
||
@item number_of_clauses(@var{ClauseCount})
|
||
Number of clauses in the predicate definition. Always one if external
|
||
or built-in.
|
||
@end table
|
||
|
||
@end table
|
||
|
||
@node Database References, Internal Database, Looking at the Database, Database
|
||
@subsection Using Data Base References
|
||
|
||
Data Base references are a fast way of accessing terms. The predicates
|
||
@code{erase/1} and @code{instance/1} also apply to these references and may
|
||
sometimes be used instead of @code{retract/1} and @code{clause/2}.
|
||
|
||
@table @code
|
||
|
||
@item assert(+@var{C},-@var{R})
|
||
@findex assert/2
|
||
@saindex assert/2
|
||
@caindex assert/2
|
||
The same as @code{assert(C)} (@pxref{Modifying the Database}) but
|
||
unifies @var{R} with the database reference that identifies the new
|
||
clause, in a one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item asserta(+@var{C},-@var{R})
|
||
@findex asserta/2
|
||
@saindex asserta/2
|
||
@caindex asserta/2
|
||
The same as @code{asserta(C)} but unifying @var{R} with
|
||
the database reference that identifies the new clause, in a
|
||
one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item assertz(+@var{C},-@var{R})
|
||
@findex assertz/2
|
||
@saindex assertz/2
|
||
@caindex assertz/2
|
||
The same as @code{assertz(C)} but unifying @var{R} with
|
||
the database reference that identifies the new clause, in a
|
||
one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item retract(+@var{C},-@var{R})
|
||
@findex retract/2
|
||
@saindex retract/2
|
||
@caindex retract/2
|
||
Erases from the program the clause @var{C} whose
|
||
database reference is @var{R}. The predicate must be dynamic.
|
||
|
||
|
||
@end table
|
||
|
||
@node Internal Database, BlackBoard, Database References, Database
|
||
@section Internal Data Base
|
||
Some programs need global information for, e.g. counting or collecting
|
||
data obtained by backtracking. As a rule, to keep this information, the
|
||
internal data base should be used instead of asserting and retracting
|
||
clauses (as most novice programmers do), .
|
||
In YAP (as in some other Prolog systems) the internal data base (i.d.b.
|
||
for short) is faster, needs less space and provides a better insulation of
|
||
program and data than using asserted/retracted clauses.
|
||
The i.d.b. is implemented as a set of terms, accessed by keys that
|
||
unlikely what happens in (non-Prolog) data bases are not part of the
|
||
term. Under each key a list of terms is kept. References are provided so that
|
||
terms can be identified: each term in the i.d.b. has a unique reference
|
||
(references are also available for clauses of dynamic predicates).
|
||
|
||
@table @code
|
||
|
||
@item recorda(+@var{K},@var{T},-@var{R})
|
||
@findex recorda/3
|
||
@saindex recorda/3
|
||
@cyindex recorda/3
|
||
Makes term @var{T} the first record under key @var{K} and unifies @var{R}
|
||
with its reference.
|
||
|
||
@item recordz(+@var{K},@var{T},-@var{R})
|
||
@findex recordz/3
|
||
@saindex recordz/3
|
||
@cyindex recordz/3
|
||
Makes term @var{T} the last record under key @var{K} and unifies @var{R}
|
||
with its reference.
|
||
|
||
@item recorda_at(+@var{R0},@var{T},-@var{R})
|
||
@findex recorda_at/3
|
||
@snindex recorda_at/3
|
||
@cnindex recorda_at/3
|
||
Makes term @var{T} the record preceding record with reference
|
||
@var{R0}, and unifies @var{R} with its reference.
|
||
|
||
@item recordz_at(+@var{R0},@var{T},-@var{R})
|
||
@findex recordz_at/3
|
||
@snindex recordz_at/3
|
||
@cnindex recordz_at/3
|
||
Makes term @var{T} the record following record with reference
|
||
@var{R0}, and unifies @var{R} with its reference.
|
||
|
||
@item recordaifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordaifnot/3
|
||
@saindex recordaifnot/3
|
||
@cnindex recordaifnot/3
|
||
If a term equal to @var{T} up to variable renaming is stored under key
|
||
@var{K} fail. Otherwise, make term @var{T} the first record under key
|
||
@var{K} and unify @var{R} with its reference.
|
||
|
||
@item recordzifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recorda/3
|
||
@snindex recorda/3
|
||
@cnindex recorda/3
|
||
If a term equal to @var{T} up to variable renaming is stored under key
|
||
@var{K} fail. Otherwise, make term @var{T} the first record under key
|
||
@var{K} and unify @var{R} with its reference.
|
||
|
||
@item recorded(+@var{K},@var{T},@var{R})
|
||
@findex recorded/3
|
||
@saindex recorded/3
|
||
@cyindex recorded/3
|
||
Searches in the internal database under the key @var{K}, a term that
|
||
unifies with @var{T} and whose reference matches @var{R}. This
|
||
built-in may be used in one of two ways:
|
||
@itemize @bullet
|
||
@item @var{K} may be given, in this case the built-in will return all
|
||
elements of the internal data-base that match the key.
|
||
@item @var{R} may be given, if so returning the key and element that
|
||
match the reference.
|
||
@end itemize
|
||
|
||
@item nth_instance(?@var{K},?@var{Index},@var{T},?@var{R})
|
||
@findex nth_recorded/3
|
||
@saindex nth_recorded/3
|
||
@cnindex nth_recorded/3
|
||
Fetches the @var{Index}nth entry in the internal database under the
|
||
key @var{K}. Entries are numbered from one. If the key @var{K} are the
|
||
@var{Index} are bound, a reference is unified with @var{R}. Otherwise,
|
||
the reference @var{R} must be given, and the term the system will find
|
||
the matching key and index.
|
||
|
||
@item erase(+@var{R})
|
||
@findex erase/1
|
||
@saindex erase/1
|
||
@cyindex erase/1
|
||
The term referred to by @var{R} is erased from the internal database. If
|
||
reference @var{R} does not exist in the database, @code{erase} just fails.
|
||
|
||
@item erased(+@var{R})
|
||
@findex erased/1
|
||
@saindex erased/1
|
||
@cyindex erased/1
|
||
Succeeds if the object whose database reference is @var{R} has been
|
||
erased.
|
||
|
||
@item instance(+@var{R},-@var{T})
|
||
@findex instance/2
|
||
@saindex instance/2
|
||
@cyindex instance/2
|
||
If @var{R} refers to a clause or a recorded term, @var{T} is unified
|
||
with its most general instance. If @var{R} refers to an unit clause
|
||
@var{C}, then @var{T} is unified with @code{@var{C} :- true}. When
|
||
@var{R} is not a reference to an existing clause or to a recorded term,
|
||
this goal fails.
|
||
|
||
@item eraseall(+@var{K})
|
||
@findex eraseall/1
|
||
@snindex eraseall/1
|
||
@cnindex eraseall/1
|
||
All terms belonging to the key @code{K} are erased from the internal
|
||
database. The predicate always succeeds.
|
||
|
||
@item current_key(?@var{A},?@var{K})
|
||
@findex current_key/2
|
||
@syindex current_key/2
|
||
@cnindex current_key/2
|
||
Defines the relation: @var{K} is a currently defined database key whose
|
||
name is the atom @var{A}. It can be used to generate all the keys for
|
||
the internal data-base.
|
||
|
||
@item key_statistics(+@var{K},-@var{Entries},-@var{Size},-@var{IndexSize})
|
||
@findex key_statistics/4
|
||
@snindex key_statistics/4
|
||
@cnindex key_statistics/4
|
||
Returns several statistics for a key @var{K}. Currently, it says how
|
||
many entries we have for that key, @var{Entries}, what is the
|
||
total size spent on entries, @var{Size}, and what is the amount of
|
||
space spent in indices.
|
||
|
||
@item key_statistics(+@var{K},-@var{Entries},-@var{TotalSize})
|
||
@findex key_statistics/3
|
||
@snindex key_statistics/3
|
||
@cnindex key_statistics/3
|
||
Returns several statistics for a key @var{K}. Currently, it says how
|
||
many entries we have for that key, @var{Entries}, what is the
|
||
total size spent on this key.
|
||
|
||
@item get_value(+@var{A},-@var{V})
|
||
@findex get_value/2
|
||
@snindex get_value/2
|
||
@cnindex get_value/2
|
||
In YAP, atoms can be associated with constants. If one such
|
||
association exists for atom @var{A}, unify the second argument with the
|
||
constant. Otherwise, unify @var{V} with @code{[]}.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@item set_value(+@var{A},+@var{C})
|
||
@findex set_value/2
|
||
@snindex set_value/2
|
||
@cnindex set_value/2
|
||
Associate atom @var{A} with constant @var{C}.
|
||
|
||
The @code{set_value} and @code{get_value} built-ins give a fast alternative to
|
||
the internal data-base. This is a simple form of implementing a global
|
||
counter.
|
||
@example
|
||
read_and_increment_counter(Value) :-
|
||
get_value(counter, Value),
|
||
Value1 is Value+1,
|
||
set_value(counter, Value1).
|
||
@end example
|
||
@noindent
|
||
This predicate is YAP specific.
|
||
|
||
@item recordzifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordzifnot/3
|
||
@snindex recordzifnot/3
|
||
@cnindex recordzifnot/3
|
||
If a variant of @var{T} is stored under key @var{K} fail. Otherwise, make
|
||
term @var{T} the last record under key @var{K} and unify @var{R} with its
|
||
reference.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@item recordaifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordaifnot/3
|
||
@snindex recordaifnot/3
|
||
@cnindex recordaifnot/3
|
||
If a variant of @var{T} is stored under key @var{K} fail. Otherwise, make
|
||
term @var{T} the first record under key @var{K} and unify @var{R} with its
|
||
reference.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@end table
|
||
|
||
There is a strong analogy between the i.d.b. and the way dynamic
|
||
predicates are stored. In fact, the main i.d.b. predicates might be
|
||
implemented using dynamic predicates:
|
||
|
||
@example
|
||
recorda(X,T,R) :- asserta(idb(X,T),R).
|
||
recordz(X,T,R) :- assertz(idb(X,T),R).
|
||
recorded(X,T,R) :- clause(idb(X,T),R).
|
||
@end example
|
||
@noindent
|
||
We can take advantage of this, the other way around, as it is quite
|
||
easy to write a simple Prolog interpreter, using the i.d.b.:
|
||
|
||
@example
|
||
asserta(G) :- recorda(interpreter,G,_).
|
||
assertz(G) :- recordz(interpreter,G,_).
|
||
retract(G) :- recorded(interpreter,G,R), !, erase(R).
|
||
call(V) :- var(V), !, fail.
|
||
call((H :- B)) :- !, recorded(interpreter,(H :- B),_), call(B).
|
||
call(G) :- recorded(interpreter,G,_).
|
||
@end example
|
||
@noindent
|
||
In YAP, much attention has been given to the implementation of the
|
||
i.d.b., especially to the problem of accelerating the access to terms kept in
|
||
a large list under the same key. Besides using the key, YAP uses an internal
|
||
lookup function, transparent to the user, to find only the terms that might
|
||
unify. For instance, in a data base containing the terms
|
||
|
||
@example
|
||
b
|
||
b(a)
|
||
c(d)
|
||
e(g)
|
||
b(X)
|
||
e(h)
|
||
@end example
|
||
|
||
@noindent
|
||
stored under the key k/1, when executing the query
|
||
|
||
@example
|
||
:- recorded(k(_),c(_),R).
|
||
@end example
|
||
|
||
@noindent
|
||
@code{recorded} would proceed directly to the third term, spending almost the
|
||
time as if @code{a(X)} or @code{b(X)} was being searched.
|
||
The lookup function uses the functor of the term, and its first three
|
||
arguments (when they exist). So, @code{recorded(k(_),e(h),_)} would go
|
||
directly to the last term, while @code{recorded(k(_),e(_),_)} would find
|
||
first the fourth term, and then, after backtracking, the last one.
|
||
|
||
This mechanism may be useful to implement a sort of hierarchy, where
|
||
the functors of the terms (and eventually the first arguments) work as
|
||
secondary keys.
|
||
|
||
In the YAP's i.d.b. an optimized representation is used for
|
||
terms without free variables. This results in a faster retrieval of terms
|
||
and better space usage. Whenever possible, avoid variables in terms in terms stored in the i.d.b.
|
||
|
||
|
||
@node BlackBoard, , Internal Database, Database
|
||
@section The Blackboard
|
||
|
||
YAP implements a blackboard in the style of the SICStus Prolog
|
||
blackboard. The blackboard uses the same underlying mechanism as the
|
||
internal data-base but has several important differences:
|
||
@itemize @bullet
|
||
@item It is module aware, in contrast to the internal data-base.
|
||
@item Keys can only be atoms or integers, and not compound terms.
|
||
@item A single term can be stored per key.
|
||
@item An atomic update operation is provided; this is useful for
|
||
parallelism.
|
||
@end itemize
|
||
|
||
|
||
@table @code
|
||
@item bb_put(+@var{Key},?@var{Term})
|
||
@findex bb_put/2
|
||
@syindex bb_put/2
|
||
@cnindex bb_put/2
|
||
Store term table @var{Term} in the blackboard under key @var{Key}. If a
|
||
previous term was stored under key @var{Key} it is simply forgotten.
|
||
|
||
@item bb_get(+@var{Key},?@var{Term})
|
||
@findex bb_get/2
|
||
@syindex bb_get/2
|
||
@cnindex bb_get/2
|
||
Unify @var{Term} with a term stored in the blackboard under key
|
||
@var{Key}, or fail silently if no such term exists.
|
||
|
||
@item bb_delete(+@var{Key},?@var{Term})
|
||
@findex bb_delete/2
|
||
@syindex bb_delete/2
|
||
@cnindex bb_delete/2
|
||
Delete any term stored in the blackboard under key @var{Key} and unify
|
||
it with @var{Term}. Fail silently if no such term exists.
|
||
|
||
@item bb_update(+@var{Key},?@var{Term},?@var{New})
|
||
@findex bb_update/3
|
||
@syindex bb_update/3
|
||
@cnindex bb_update/3
|
||
Atomically unify a term stored in the blackboard under key @var{Key}
|
||
with @var{Term}, and if the unification succeeds replace it by
|
||
@var{New}. Fail silently if no such term exists or if unification fails.
|
||
|
||
@end table
|
||
|
||
@node Sets, Grammars, Database, Top
|
||
@section Collecting Solutions to a Goal
|
||
|
||
When there are several solutions to a goal, if the user wants to collect all
|
||
the solutions he may be led to use the data base, because backtracking will
|
||
forget previous solutions.
|
||
|
||
YAP allows the programmer to choose from several system
|
||
predicates instead of writing his own routines. @code{findall/3} gives you
|
||
the fastest, but crudest solution. The other built-in predicates
|
||
post-process the result of the query in several different ways:
|
||
|
||
@table @code
|
||
|
||
@item findall(@var{T},+@var{G},-@var{L}) [ISO]
|
||
@findex findall/3
|
||
@syindex findall/3
|
||
@cyindex findall/3
|
||
Unifies @var{L} with a list that contains all the instantiations of the
|
||
term @var{T} satisfying the goal @var{G}.
|
||
|
||
With the following program:
|
||
@example
|
||
a(2,1).
|
||
a(1,1).
|
||
a(2,2).
|
||
@end example
|
||
@noindent
|
||
the answer to the query
|
||
@example
|
||
findall(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
@example
|
||
X = _32
|
||
Y = _33
|
||
L = [2,1,2];
|
||
no
|
||
@end example
|
||
|
||
@item findall(@var{T},+@var{G},+@var{L},-@var{L0})
|
||
@findex findall/4
|
||
@syindex findall/4
|
||
@cnindex findall/4
|
||
Similar to @code{findall/3}, but appends all answers to list @var{L0}.
|
||
|
||
@item all(@var{T},+@var{G},-@var{L})
|
||
@findex all/3
|
||
@snindex all/3
|
||
@cnindex all/3
|
||
Similar to @code{findall(@var{T},@var{G},@var{L})} but eliminating
|
||
repeated elements. Thus, assuming the same clauses as in the above
|
||
example, the reply to the query
|
||
|
||
@example
|
||
all(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
|
||
@example
|
||
X = _32
|
||
Y = _33
|
||
L = [2,1];
|
||
no
|
||
@end example
|
||
|
||
@item bagof(@var{T},+@var{G},-@var{L}) [ISO]
|
||
@findex bagof/3
|
||
@saindex bagof/3
|
||
@cyindex bagof/3
|
||
For each set of possible instances of the free variables occurring in
|
||
@var{G} but not in @var{T}, generates the list @var{L} of the instances of
|
||
@var{T} satisfying @var{G}. Again, assuming the same clauses as in the
|
||
examples above, the reply to the query
|
||
|
||
@example
|
||
bagof(X,a(X,Y),L).
|
||
|
||
would be:
|
||
X = _32
|
||
Y = 1
|
||
L = [2,1];
|
||
X = _32
|
||
Y = 2
|
||
L = [2];
|
||
no
|
||
@end example
|
||
|
||
@item setof(@var{X},+@var{P},-@var{B}) [ISO]
|
||
@findex setof/3
|
||
@saindex setof/3
|
||
@cyindex setof/3
|
||
Similar to @code{bagof(@var{T},@var{G},@var{L})} but sorting list
|
||
@var{L} and keeping only one copy of each element. Again, assuming the
|
||
same clauses as in the examples above, the reply to the query
|
||
@example
|
||
setof(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
@example
|
||
X = _32
|
||
Y = 1
|
||
L = [1,2];
|
||
X = _32
|
||
Y = 2
|
||
L = [2];
|
||
no
|
||
@end example
|
||
|
||
@end table
|
||
|
||
@node Grammars, OS, Sets, Top
|
||
@section Grammar Rules
|
||
|
||
Grammar rules in Prolog are both a convenient way to express definite
|
||
clause grammars and an extension of the well known context-free grammars.
|
||
|
||
A grammar rule is of the form:
|
||
|
||
@example
|
||
@i{ head --> body }
|
||
@end example
|
||
@noindent
|
||
where both @i{head} and @i{body} are sequences of one or more items
|
||
linked by the standard conjunction operator ','.
|
||
|
||
@emph{Items can be:}
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a @emph{non-terminal} symbol may be either a complex term or an atom.
|
||
@item
|
||
a @emph{terminal} symbol may be any Prolog symbol. Terminals are
|
||
written as Prolog lists.
|
||
@item
|
||
an @emph{empty body} is written as the empty list '[ ]'.
|
||
@item
|
||
@emph{extra conditions} may be inserted as Prolog procedure calls, by being
|
||
written inside curly brackets '@{' and '@}'.
|
||
@item
|
||
the left side of a rule consists of a nonterminal and an optional list
|
||
of terminals.
|
||
@item
|
||
alternatives may be stated in the right-hand side of the rule by using
|
||
the disjunction operator ';'.
|
||
@item
|
||
the @emph{cut} and @emph{conditional} symbol ('->') may be inserted in the
|
||
right hand side of a grammar rule
|
||
@end itemize
|
||
|
||
Grammar related built-in predicates:
|
||
|
||
@table @code
|
||
|
||
@item expand_term(@var{T},-@var{X})
|
||
@findex expand_term/2
|
||
@syindex expand_term/2
|
||
@cyindex expand_term/2
|
||
@findex term_expansion/2
|
||
@syindex term_expansion/2
|
||
@cyindex term_expansion/2
|
||
This predicate is used by YAP for preprocessing each top level
|
||
term read when consulting a file and before asserting or executing it.
|
||
It rewrites a term @var{T} to a term @var{X} according to the following
|
||
rules: first try to use the user defined predicate
|
||
@code{term_expansion/2}. If this call fails then the translating process
|
||
for DCG rules is applied, together with the arithmetic optimizer
|
||
whenever the compilation of arithmetic expressions is in progress.
|
||
|
||
@item user:goal_expansion(+@var{G},+@var{M},-@var{NG})
|
||
@findex goal_expansion/3
|
||
@snindex goal_expansion/3
|
||
@cnindex goal_expansion/3
|
||
Yap now supports @code{goal_expansion/3}. This is an user-defined
|
||
procedure that is called after term expansion when compiling or
|
||
asserting goals for each sub-goal in a clause. The first argument is
|
||
bound to the goal and the second to the module under which the goal
|
||
@var{G} will execute. If @code{goal_expansion/3} succeeds the new
|
||
sub-goal @var{NG} will replace @var{G} and will be processed in the same
|
||
way. If @code{goal_expansion/3} fails the system will use the default
|
||
rules.
|
||
|
||
@item phrase(+@var{P},@var{L},@var{R})
|
||
@findex phrase/3
|
||
@syindex phrase/3
|
||
@cnindex phrase/3
|
||
This predicate succeeds when the difference list @code{@var{L}-@var{R}}
|
||
is a phrase of type @var{P}.
|
||
|
||
@item phrase(+@var{P},@var{L})
|
||
@findex phrase/2
|
||
@syindex phrase/2
|
||
@cnindex phrase/2
|
||
This predicate succeeds when @var{L} is a phrase of type @var{P}. The
|
||
same as @code{phrase(P,L,[])}.
|
||
|
||
Both this predicate and the previous are used as a convenient way to
|
||
start execution of grammar rules.
|
||
|
||
@item 'C'(@var{S1},@var{T},@var{S2})
|
||
@findex C/3
|
||
@syindex C/3
|
||
@cnindex C/3
|
||
This predicate is used by the grammar rules compiler and is defined as
|
||
@code{'C'([H|T],H,T)}.
|
||
|
||
@end table
|
||
|
||
@node OS, Term Modification, Grammars, Top
|
||
@section Access to Operating System Functionality
|
||
|
||
The following built-in predicates allow access to underlying
|
||
Operating System functionality:
|
||
|
||
@table @code
|
||
|
||
@item cd(+@var{D})
|
||
@findex cd/1
|
||
@snindex cd/1
|
||
@cnindex cd/1
|
||
Changes the current directory (on UNIX environments).
|
||
|
||
@item environ(+@var{E},-@var{S})
|
||
@findex environ/2
|
||
@syindex environ/2
|
||
@cnindex environ/2
|
||
@comment This backtrackable predicate unifies the first argument with an
|
||
@comment environment variable @var{E}, and the second with its value @var{S}. It
|
||
@comment can used to detect all environment variables.
|
||
Given an environment variable @var{E} this predicate unifies the second argument @var{S} with its value.
|
||
|
||
@item getcwd(-@var{D})
|
||
@findex getcwd/1
|
||
@snindex getcwd/1
|
||
@cnindex getcwd/1
|
||
Unify the current directory, represented as an atom, with the argument
|
||
@var{D}.
|
||
|
||
@item putenv(+@var{E},+@var{S})
|
||
@findex putenv/2
|
||
@snindex putenv/2
|
||
@cnindex putenv/2
|
||
Set environment variable @var{E} to the value @var{S}. If the
|
||
environment variable @var{E} does not exist, create a new one. Both the
|
||
environment variable and the value must be atoms.
|
||
|
||
@item rename(+@var{F},+@var{G})
|
||
@findex rename/2
|
||
@snindex rename/2
|
||
@cyindex rename/2
|
||
Renames file @var{F} to @var{G}.
|
||
|
||
@item sh
|
||
@findex sh/0
|
||
@snindex sh/0
|
||
@cyindex sh/0
|
||
Creates a new shell interaction.
|
||
|
||
@item system(+@var{S})
|
||
@findex system/1
|
||
@snindex system/1
|
||
@cyindex system/1
|
||
Passes command @var{S} to the Bourne shell (on UNIX environments) or the
|
||
current command interpreter in WIN32 environments.
|
||
|
||
@item unix(+@var{S})
|
||
@findex unix/1
|
||
@snindex unix/1
|
||
@cnindex unix/1
|
||
Access to Unix-like functionality:
|
||
@table @code
|
||
@item argv/1
|
||
Return a list of arguments to the program. These are the arguments that
|
||
follow a @code{--}, as in the usual Unix convention.
|
||
@item cd/0
|
||
Change to home directory.
|
||
@item cd/1
|
||
Change to given directory. Acceptable directory names are strings or
|
||
atoms.
|
||
@item environ/2
|
||
If the first argument is an atom, unify the second argument with the
|
||
value of the corresponding environment variable.
|
||
@item getcwd/1
|
||
Unify the first argument with an atom representing the current directory.
|
||
@item putenv/2
|
||
Set environment variable @var{E} to the value @var{S}. If the
|
||
environment variable @var{E} does not exist, create a new one. Both the
|
||
environment variable and the value must be atoms.
|
||
@item shell/1
|
||
Execute command under current shell. Acceptable commands are strings or
|
||
atoms.
|
||
@item system/1
|
||
Execute command with @code{/bin/sh}. Acceptable commands are strings or
|
||
atoms.
|
||
@item shell/0
|
||
Execute a new shell.
|
||
@end table
|
||
|
||
@item alarm(+@var{Seconds},+@var{Callable},+@var{OldAlarm})
|
||
@findex alarm/3
|
||
@snindex alarm/3
|
||
@cnindex alarm/3
|
||
Arranges for YAP to be interrupted in @var{Seconds}
|
||
seconds. When interrupted, YAP will execute @var{Callable} and
|
||
then return to the previous execution. If @var{Seconds} is @code{0}, no
|
||
new alarm is scheduled. In any event, any previously set alarm is
|
||
canceled.
|
||
|
||
The variable @var{OldAlarm} unifies with the number of seconds remaining
|
||
until any previously scheduled alarm was due to be delivered, or with
|
||
@code{0} if there was no previously scheduled alarm.
|
||
|
||
Note that execution of @var{Callable} will wait if YAP is
|
||
executing built-in predicates, such as Input/Output operations.
|
||
|
||
The next example shows how @var{alarm/3} can be used to implement a
|
||
simple clock:
|
||
|
||
@example
|
||
loop :- loop.
|
||
|
||
ticker :- write('.'), flush_output,
|
||
get_value(tick, yes),
|
||
alarm(1,ticker,_).
|
||
|
||
:- set_value(tick, yes), alarm(1,ticker,_), loop.
|
||
@end example
|
||
|
||
The clock, @code{ticker}, writes a dot and then checks the flag
|
||
@code{tick} to see whether it can continue ticking. If so, it calls
|
||
itself again. Note that there is no guarantee that the each dot
|
||
corresponds a second: for instance, if the YAP is waiting for
|
||
user input, @code{ticker} will wait until the user types the entry in.
|
||
|
||
The next example shows how @code{alarm/3} can be used to guarantee that
|
||
a certain procedure does not take longer than a certain amount of time:
|
||
|
||
@example
|
||
loop :- loop.
|
||
|
||
:- catch((alarm(10, throw(ball), _),loop),
|
||
ball,
|
||
format('Quota exhausted.~n',[])).
|
||
@end example
|
||
In this case after @code{10} seconds our @code{loop} is interrupted,
|
||
@code{ball} is thrown, and the handler writes @code{Quota exhausted}.
|
||
Execution then continues from the handler.
|
||
|
||
Note that in this case @code{loop/0} always executes until the alarm is
|
||
sent. Often, the code you are executing succeeds or fails before the
|
||
alarm is actually delivered. In this case, you probably want to disable
|
||
the alarm when you leave the procedure. The next procedure does exactly so:
|
||
@example
|
||
once_with_alarm(Time,Goal,DoOnAlarm) :-
|
||
catch(execute_once_with_alarm(Time, Goal), alarm, DoOnAlarm).
|
||
|
||
execute_once_with_alarm(Time, Goal) :-
|
||
alarm(Time, alarm, _),
|
||
( call(Goal) -> alarm(0, alarm, _) ; alarm(0, alarm, _), fail).
|
||
@end example
|
||
|
||
The procedure has three arguments: the @var{Time} before the alarm is
|
||
sent; the @var{Goal} to execute; and the goal @var{DoOnAlarm} to execute
|
||
if the alarm is sent. It uses @code{catch/3} to handle the case the
|
||
@code{alarm} is sent. Then it starts the alarm, calls the goal
|
||
@var{Goal}, and disables the alarm on success or failure.
|
||
|
||
@item on_signal(+@var{Signal},?@var{OldAction},+@var{Callable})
|
||
@findex on_signal/3
|
||
@snindex on_signal/3
|
||
@cnindex on_signal/3
|
||
Set the interrupt handler for soft interrupt @var{Signal} to be
|
||
@var{Callable}. @var{OldAction} is unified with the previous handler.
|
||
|
||
Only a subset of the software interrupts (signals) can have their
|
||
handlers manipulated through @code{on_signal/3}.
|
||
Their POSIX names, YAP names and default behavior is given below.
|
||
The "YAP name" of the signal is the atom that is associated with
|
||
each signal, and should be used as the first argument to
|
||
@code{on_signal/3}. It is chosen so that it matches the signal's POSIX
|
||
name.
|
||
|
||
@code{on_signal/3} succeeds, unless when called with an invalid
|
||
signal name or one that is not supported on this platform. No checks
|
||
are made on the handler provided by the user.
|
||
|
||
@table @code
|
||
@item sig_up (Hangup)
|
||
SIGHUP in Unix/Linux; Reconsult the initialization files
|
||
~/.yaprc, ~/.prologrc and ~/prolog.ini.
|
||
@item sig_usr1 and sig_usr2 (User signals)
|
||
SIGUSR1 and SIGUSR2 in Unix/Linux; Print a message and halt.
|
||
@end table
|
||
|
||
A special case is made, where if @var{Callable} is bound to
|
||
@code{default}, then the default handler is restored for that signal.
|
||
|
||
A call in the form @code{on_signal(@var{S},@var{H},@var{H})} can be used
|
||
to retrieve a signal's current handler without changing it.
|
||
|
||
It must be noted that although a signal can be received at all times,
|
||
the handler is not executed while Yap is waiting for a query at the
|
||
prompt. The signal will be, however, registered and dealt with as soon
|
||
as the user makes a query.
|
||
|
||
Please also note, that neither POSIX Operating Systems nor Yap guarantee
|
||
that the order of delivery and handling is going to correspond with the
|
||
order of dispatch.
|
||
|
||
@end table
|
||
|
||
@node Term Modification, Profiling, OS, Top
|
||
@section Term Modification
|
||
|
||
@cindex updating terms
|
||
It is sometimes useful to change the value of instantiated
|
||
variables. Although, this is against the spirit of logic programming, it
|
||
is sometimes useful. As in other Prolog systems, YAP has
|
||
several primitives that allow updating Prolog terms. Note that these
|
||
primitives are also backtrackable.
|
||
|
||
The @code{setarg/3} primitive allows updating any argument of a Prolog
|
||
compound terms. The @code{mutable} family of predicates provides
|
||
@emph{mutable variables}. They should be used instead of @code{setarg/3},
|
||
as they allow the encapsulation of accesses to updatable
|
||
variables. Their implementation can also be more efficient for long
|
||
deterministic computations.
|
||
|
||
@table @code
|
||
@item setarg(+@var{I},+@var{S},?@var{T})
|
||
@findex setarg/3n
|
||
@snindex setarg/3n
|
||
@cnindex setarg/3n
|
||
Set the value of the @var{I}th argument of term @var{S} to term @var{T}.
|
||
|
||
@cindex mutable variables
|
||
@item create_mutable(+@var{D},-@var{M})
|
||
@findex create_mutable/2
|
||
@syindex create_mutable/2
|
||
@cnindex create_mutable/2
|
||
Create new mutable variable @var{M} with initial value @var{D}.
|
||
|
||
@item get_mutable(?@var{D},+@var{M})
|
||
@findex get_mutable/2
|
||
@syindex get_mutable/2
|
||
@cnindex get_mutable/2
|
||
Unify the current value of mutable term @var{M} with term @var{D}.
|
||
|
||
@item is_mutable(?@var{D})
|
||
@findex is_mutable/1
|
||
@syindex is_mutable/1
|
||
@cnindex is_mutable/1
|
||
Holds if @var{D} is a mutable term.
|
||
|
||
@item get_mutable(?@var{D},+@var{M})
|
||
@findex get_mutable/2
|
||
@syindex get_mutable/2
|
||
@cnindex get_mutable/2
|
||
Unify the current value of mutable term @var{M} with term @var{D}.
|
||
|
||
@item update_mutable(+@var{D},+@var{M})
|
||
@findex update_mutable/2
|
||
@syindex update_mutable/2
|
||
@cnindex update_mutable/2
|
||
Set the current value of mutable term @var{M} to term @var{D}.
|
||
@end table
|
||
|
||
@node Profiling, Call Counting, Term Modification, Top
|
||
@section Profiling Prolog Programs
|
||
|
||
@cindex profiling
|
||
|
||
YAP includes two profiler. The count profiler keeps information on the
|
||
number of times a predicate was called. This information can be used to
|
||
detect what are the most commonly called predicates in the program. The
|
||
count profiler can be compiled by setting YAP's flag @code{profiling}
|
||
to @code{on}. The time-profiler is a @code{gprof} profiler, and counts
|
||
how many ticks are being spent on specific predicates, or on other
|
||
system functions such as internal data-base accesses or garbage collects.
|
||
|
||
The YAP profiling sub-system is currently under
|
||
development. Functionality for this sub-system will increase with newer
|
||
implementation.
|
||
|
||
@subsection The Count Profiler
|
||
|
||
@strong{Notes:}
|
||
|
||
The count profiler works by incrementing counters at procedure entry or
|
||
backtracking. It provides exact information:
|
||
|
||
@itemize @bullet
|
||
@item Profiling works for both static and dynamic predicates.
|
||
@item Currently only information on entries and retries to a predicate
|
||
are maintained. This may change in the future.
|
||
@item As an example, the following user-level program gives a list of
|
||
the most often called procedures in a program. The procedure
|
||
@code{list_profile} shows all procedures, irrespective of module, and
|
||
the procedure @code{list_profile/1} shows the procedures being used in
|
||
a specific module.
|
||
@example
|
||
list_profile :-
|
||
% get number of calls for each profiled procedure
|
||
setof(D-[M:P|D1],(current_module(M),profile_data(M:P,calls,D),profile_data(M:P,retries,D1)),LP),
|
||
% output so that the most often called
|
||
% predicates will come last:
|
||
write_profile_data(LP).
|
||
|
||
list_profile(Module) :-
|
||
% get number of calls for each profiled procedure
|
||
setof(D-[Module:P|D1],(profile_data(Module:P,calls,D),profile_data(Module:P,retries,D1)),LP),
|
||
% output so that the most often called
|
||
% predicates will come last:
|
||
write_profile_data(LP).
|
||
|
||
write_profile_data([]).
|
||
write_profile_data([D-[M:P|R]|SLP]) :-
|
||
% swap the two calls if you want the most often
|
||
% called predicates first.
|
||
format('~a:~w: ~32+~t~d~12+~t~d~12+~n', [M,P,D,R]),
|
||
write_profile_data(SLP).
|
||
@end example
|
||
@end itemize
|
||
|
||
These are the current predicates to access and clear profiling data:
|
||
|
||
@table @code
|
||
@item profile_data(?@var{Na/Ar}, ?@var{Parameter}, -@var{Data})
|
||
@findex profile_data/3
|
||
@snindex profile_data/3
|
||
@cnindex profile_data/3
|
||
Give current profile data on @var{Parameter} for a predicate described
|
||
by the predicate indicator @var{Na/Ar}. If any of @var{Na/Ar} or
|
||
@var{Parameter} are unbound, backtrack through all profiled predicates
|
||
or stored parameters. Current parameters are:
|
||
|
||
@table @code
|
||
@item calls
|
||
Number of times a procedure was called.
|
||
|
||
@item retries
|
||
Number of times a call to the procedure was backtracked to and retried.
|
||
@end table
|
||
|
||
@item profile_reset
|
||
@findex profiled_reset/0
|
||
@snindex profiled_reset/0
|
||
@cnindex profiled_reset/0
|
||
Reset all profiling information.
|
||
|
||
@end table
|
||
|
||
@subsection Tick Profiler
|
||
The tick profiler works by interrupting the Prolog code every so often
|
||
and checking at each point the code was. The profiler must be able to
|
||
retrace the state of the abstract machine at every moment. The major
|
||
advantage of this approach is that it gives the actual amount of time
|
||
being spent per procedure, or whether garbage collection dominates
|
||
execution time. The major drawback is that tracking down the state of
|
||
the abstract machine may take significant time, and in the worst case
|
||
may slow down the whole execution.
|
||
|
||
The following procedures are available:
|
||
|
||
@table @code
|
||
@item profinit
|
||
@findex profinit/0
|
||
@snindex profinit/0
|
||
@cnindex profinit/0
|
||
Initialise the data-structures for the profiler.
|
||
|
||
@item profon
|
||
@findex profon/0
|
||
@snindex profon/0
|
||
@cnindex profon/0
|
||
Start profiling.
|
||
|
||
@item profoff
|
||
@findex profoff/0
|
||
@snindex profoff/0
|
||
@cnindex profoff/0
|
||
Stop profiling.
|
||
|
||
@item showprofres
|
||
@findex showprofres/0
|
||
@snindex showprofres/0
|
||
@cnindex showprofres/0
|
||
Show profiling info.
|
||
|
||
@item showprofres(@var{N})
|
||
@findex showprofres/1
|
||
@snindex showprofres/1
|
||
@cnindex showprofres/1
|
||
Show profiling info for the top-most @var{N} predicates.
|
||
|
||
@end table
|
||
|
||
|
||
@node Call Counting, Arrays, Profiling, Top
|
||
@section Counting Calls
|
||
|
||
@cindex Counting Calls
|
||
Predicates compiled with YAP's flag @code{call_counting} set to
|
||
@code{on} update counters on the numbers of calls and of
|
||
retries. Counters are actually decreasing counters, so that they can be
|
||
used as timers. Three counters are available:
|
||
@itemize @bullet
|
||
@item @code{calls}: number of predicate calls since execution started or since
|
||
system was reset;
|
||
@item @code{retries}: number of retries for predicates called since
|
||
execution started or since counters were reset;
|
||
@item @code{calls_and_retries}: count both on predicate calls and
|
||
retries.
|
||
@end itemize
|
||
These counters can be used to find out how many calls a certain
|
||
goal takes to execute. They can also be used as timers.
|
||
|
||
The code for the call counters piggybacks on the profiling
|
||
code. Therefore, activating the call counters also activates the profiling
|
||
counters.
|
||
|
||
These are the predicates that access and manipulate the call counters:
|
||
|
||
@table @code
|
||
@item call_count_data(-@var{Calls}, -@var{Retries}, -@var{CallsAndRetries})
|
||
@findex call_count_data/3
|
||
@snindex call_count_data/3
|
||
@cnindex call_count_data/3
|
||
Give current call count data. The first argument gives the current value
|
||
for the @var{Calls} counter, next the @var{Retries} counter, and last
|
||
the @var{CallsAndRetries} counter.
|
||
|
||
@item call_count_reset
|
||
@findex call_count_data/0
|
||
@snindex call_count_data/0
|
||
@cnindex call_count_data/0
|
||
Reset call count counters. All timers are also reset.
|
||
|
||
@item call_count(?@var{CallsMax}, ?@var{RetriesMax}, ?@var{CallsAndRetriesMax})
|
||
@findex call_count_data/3
|
||
@snindex call_count_data/3
|
||
@cnindex call_count_data/3
|
||
Set call count counter as timers. YAP will generate an exception
|
||
if one of the instantiated call counters decreases to 0. YAP will ignore
|
||
unbound arguments:
|
||
@itemize @bullet
|
||
@item @var{CallsMax}: throw the exception @code{call_counter} when the
|
||
counter @code{calls} reaches 0;
|
||
@item @var{RetriesMax}: throw the exception @code{retry_counter} when the
|
||
counter @code{retries} reaches 0;
|
||
@item @var{CallsAndRetriesMax}: throw the exception
|
||
@code{call_and_retry_counter} when the counter @code{calls_and_retries}
|
||
reaches 0.
|
||
@end itemize
|
||
@end table
|
||
|
||
Next, we show a simple example of how to use call counters:
|
||
@example
|
||
?- yap_flag(call_counting,on), [-user]. l :- l. end_of_file. yap_flag(call_counting,off).
|
||
|
||
yes
|
||
|
||
yes
|
||
?- catch((call_count(10000,_,_),l),call_counter,format("limit_exceeded.~n",[])).
|
||
|
||
limit_exceeded.
|
||
|
||
yes
|
||
@end example
|
||
Notice that we first compile the looping predicate @code{l/0} with
|
||
@code{call_counting} @code{on}. Next, we @code{catch/3} to handle an
|
||
exception when @code{l/0} performs more than 10000 reductions.
|
||
|
||
|
||
@node Arrays, Preds, Call Counting , Top
|
||
@section Arrays
|
||
|
||
The YAP system includes experimental support for arrays. The
|
||
support is enabled with the option @code{YAP_ARRAYS}.
|
||
|
||
There are two very distinct forms of arrays in YAP. The
|
||
@emph{dynamic arrays} are a different way to access compound terms
|
||
created during the execution. Like any other terms, any bindings to
|
||
these terms and eventually the terms themselves will be destroyed during
|
||
backtracking. Our goal in supporting dynamic arrays is twofold. First,
|
||
they provide an alternative to the standard @code{arg/3}
|
||
built-in. Second, because dynamic arrays may have name that are globally
|
||
visible, a dynamic array can be visible from any point in the
|
||
program. In more detail, the clause
|
||
@example
|
||
g(X) :- array_element(a,2,X).
|
||
@end example
|
||
will succeed as long as the programmer has used the built-in @t{array/2}
|
||
to create an array term with at least 3 elements in the current
|
||
environment, and the array was associated with the name @code{a}. The
|
||
element @code{X} is a Prolog term, so one can bind it and any such
|
||
bindings will be undone when backtracking. Note that dynamic arrays do
|
||
not have a type: each element may be any Prolog term.
|
||
|
||
The @emph{static arrays} are an extension of the database. They provide
|
||
a compact way for manipulating data-structures formed by characters,
|
||
integers, or floats imperatively. They can also be used to provide
|
||
two-way communication between YAP and external programs through
|
||
shared memory.
|
||
|
||
In order to efficiently manage space elements in a static array must
|
||
have a type. Currently, elements of static arrays in YAP should
|
||
have one of the following predefined types:
|
||
|
||
@itemize @bullet
|
||
@item @code{byte}: an 8-bit signed character.
|
||
@item @code{unsigned_byte}: an 8-bit unsigned character.
|
||
@item @code{int}: Prolog integers. Size would be the natural size for
|
||
the machine's architecture.
|
||
@item @code{float}: Prolog floating point number. Size would be equivalent
|
||
to a double in @code{C}.
|
||
@item @code{atom}: a Prolog atom.
|
||
@item @code{dbref}: an internal database reference.
|
||
@item @code{term}: a generic Prolog term. Note that this will term will
|
||
not be stored in the array itself, but instead will be stored in the
|
||
Prolog internal database.
|
||
@end itemize
|
||
|
||
Arrays may be @emph{named} or @emph{anonymous}. Most arrays will be
|
||
@emph{named}, that is associated with an atom that will be used to find
|
||
the array. Anonymous arrays do not have a name, and they are only of
|
||
interest if the @code{TERM_EXTENSIONS} compilation flag is enabled. In
|
||
this case, the unification and parser are extended to replace
|
||
occurrences of Prolog terms of the form @code{X[I]} by run-time calls to
|
||
@code{array_element/3}, so that one can use array references instead of
|
||
extra calls to @code{arg/3}. As an example:
|
||
@example
|
||
g(X,Y,Z,I,J) :- X[I] is Y[J]+Z[I].
|
||
@end example
|
||
should give the same results as:
|
||
@example
|
||
G(X,Y,Z,I,J) :-
|
||
array_element(X,I,E1),
|
||
array_element(Y,J,E2),
|
||
array_element(Z,I,E3),
|
||
E1 is E2+E3.
|
||
@end example
|
||
|
||
Note that the only limitation on array size are the stack size for
|
||
dynamic arrays; and, the heap size for static (not memory mapped)
|
||
arrays. Memory mapped arrays are limited by available space in the file
|
||
system and in the virtual memory space.
|
||
|
||
The following predicates manipulate arrays:
|
||
|
||
@table @code
|
||
|
||
@item array(+@var{Name}, +@var{Size})
|
||
@findex array/2
|
||
@snindex array/2
|
||
@cnindex array/2
|
||
Creates a new dynamic array. The @var{Size} must evaluate to an
|
||
integer. The @var{Name} may be either an atom (named array) or an
|
||
unbound variable (anonymous array).
|
||
|
||
Dynamic arrays work as standard compound terms, hence space for the
|
||
array is recovered automatically on backtracking.
|
||
|
||
@item static_array(+@var{Name}, +@var{Size}, +@var{Type})
|
||
@findex static_array/3
|
||
@snindex static_array/3
|
||
@cnindex static_array/3
|
||
Create a new static array with name @var{Name}. Note that the @var{Name}
|
||
must be an atom (named array). The @var{Size} must evaluate to an
|
||
integer. The @var{Type} must be bound to one of types mentioned
|
||
previously.
|
||
|
||
@item static_array_location(+@var{Name}, -@var{Ptr})
|
||
@findex static_array_location/4
|
||
@snindex static_array_location/4
|
||
@cnindex static_array_location/4
|
||
Give the location for a static array with name
|
||
@var{Name}.
|
||
|
||
@item static_array_properties(?@var{Name}, ?@var{Size}, ?@var{Type})
|
||
@findex static_array_properties/3
|
||
@snindex static_array_properties/3
|
||
@cnindex static_array_properties/3
|
||
Show the properties size and type of a static array with name
|
||
@var{Name}. Can also be used to enumerate all current
|
||
static arrays.
|
||
|
||
This built-in will silently fail if the there is no static array with
|
||
that name.
|
||
|
||
@item static_array_to_term(?@var{Name}, ?@var{Term})
|
||
@findex static_array_to_term/3
|
||
@snindex static_array_to_term/3
|
||
@cnindex static_array_to_term/3
|
||
Convert a static array with name
|
||
@var{Name} to a compound term of name @var{Name}.
|
||
|
||
This built-in will silently fail if the there is no static array with
|
||
that name.
|
||
|
||
@item mmapped_array(+@var{Name}, +@var{Size}, +@var{Type}, +@var{File})
|
||
@findex static_array/3
|
||
@snindex static_array/3
|
||
@cnindex static_array/3
|
||
Similar to @code{static_array/3}, but the array is memory mapped to file
|
||
@var{File}. This means that the array is initialized from the file, and
|
||
that any changes to the array will also be stored in the file.
|
||
|
||
This built-in is only available in operating systems that support the
|
||
system call @code{mmap}. Moreover, mmapped arrays do not store generic
|
||
terms (type @code{term}).
|
||
|
||
@item close_static_array(+@var{Name})
|
||
@findex close_static_array/1
|
||
@snindex close_static_array/1
|
||
@cnindex close_static_array/1
|
||
Close an existing static array of name @var{Name}. The @var{Name} must
|
||
be an atom (named array). Space for the array will be recovered and
|
||
further accesses to the array will return an error.
|
||
|
||
@item resize_static_array(+@var{Name}, -@var{OldSize}, +@var{NewSize})
|
||
@findex resize_static_array/3
|
||
@snindex resize_static_array/3
|
||
@cnindex resize_static_array/3
|
||
Expand or reduce a static array, The @var{Size} must evaluate to an
|
||
integer. The @var{Name} must be an atom (named array). The @var{Type}
|
||
must be bound to one of @code{int}, @code{dbref}, @code{float} or
|
||
@code{atom}.
|
||
|
||
Note that if the array is a mmapped array the size of the mmapped file
|
||
will be actually adjusted to correspond to the size of the array.
|
||
|
||
@item array_element(+@var{Name}, +@var{Index}, ?@var{Element})
|
||
@findex array_element/3
|
||
@snindex array_element/3
|
||
@cnindex array_element/3
|
||
Unify @var{Element} with @var{Name}[@var{Index}]. It works for both
|
||
static and dynamic arrays, but it is read-only for static arrays, while
|
||
it can be used to unify with an element of a dynamic array.
|
||
|
||
@item update_array(+@var{Name}, +@var{Index}, ?@var{Value})
|
||
@findex update_array/3
|
||
@snindex update_array/3
|
||
@cnindex update_array/3
|
||
Attribute value @var{Value} to @var{Name}[@var{Index}]. Type
|
||
restrictions must be respected for static arrays. This operation is
|
||
available for dynamic arrays if @code{MULTI_ASSIGNMENT_VARIABLES} is
|
||
enabled (true by default). Backtracking undoes @var{update_array/3} for
|
||
dynamic arrays, but not for static arrays.
|
||
|
||
Note that @code{update_array/3} actually uses @code{setarg/3} to update
|
||
elements of dynamic arrays, and @code{setarg/3} spends an extra cell for
|
||
every update. For intensive operations we suggest it may be less
|
||
expensive to unify each element of the array with a mutable terms and
|
||
to use the operations on mutable terms.
|
||
|
||
@item add_to_array_element(+@var{Name}, +@var{Index}, , +@var{Number}, ?@var{NewValue})
|
||
@findex add_to_array_element/4
|
||
@snindex add_to_array_element/4
|
||
@cnindex add_to_array_element/4
|
||
Add @var{Number} @var{Name}[@var{Index}] and unify @var{NewValue} with
|
||
the incremented value. Observe that @var{Name}[@var{Index}] must be an
|
||
number. If @var{Name} is a static array the type of the array must be
|
||
@code{int} or @code{float}. If the type of the array is @code{int} you
|
||
only may add integers, if it is @code{float} you may add integers or
|
||
floats. If @var{Name} corresponds to a dynamic array the array element
|
||
must have been previously bound to a number and @code{Number} can be
|
||
any kind of number.
|
||
|
||
The @code{add_to_array_element/3} built-in actually uses
|
||
@code{setarg/3} to update elements of dynamic arrays. For intensive
|
||
operations we suggest it may be less expensive to unify each element
|
||
of the array with a mutable terms and to use the operations on mutable
|
||
terms.
|
||
|
||
@end table
|
||
|
||
@node Preds, Misc, Arrays, Top
|
||
@section Predicate Information
|
||
|
||
Built-ins that return information on the current predicates and modules:
|
||
|
||
@table @code
|
||
@c ......... begin of 'module' documentation .........
|
||
@item current_module(@var{M})
|
||
@findex current_module/1
|
||
@syindex current_module/1
|
||
@cnindex current_module/1
|
||
Succeeds if @var{M} are defined modules. A module is defined as soon as some
|
||
predicate defined in the module is loaded, as soon as a goal in the
|
||
module is called, or as soon as it becomes the current type-in module.
|
||
|
||
@item current_module(@var{M},@var{F})
|
||
@findex current_module/2
|
||
@syindex current_module/2
|
||
@cnindex current_module/2
|
||
Succeeds if @var{M} are current modules associated to the file @var{F}.
|
||
|
||
@c .......... end of 'module' documentation ..........
|
||
@end table
|
||
|
||
@node Misc, , Preds, Top
|
||
@section Miscellaneous
|
||
|
||
@table @code
|
||
|
||
@item statistics/0
|
||
@findex statistics/0
|
||
@saindex statistics/0
|
||
@cyindex statistics/0
|
||
Send to the current user error stream general information on space used and time
|
||
spent by the system.
|
||
@example
|
||
?- statistics.
|
||
memory (total) 4784124 bytes
|
||
program space 3055616 bytes: 1392224 in use, 1663392 free
|
||
2228132 max
|
||
stack space 1531904 bytes: 464 in use, 1531440 free
|
||
global stack: 96 in use, 616684 max
|
||
local stack: 368 in use, 546208 max
|
||
trail stack 196604 bytes: 8 in use, 196596 free
|
||
|
||
0.010 sec. for 5 code, 2 stack, and 1 trail space overflows
|
||
0.130 sec. for 3 garbage collections which collected 421000 bytes
|
||
0.000 sec. for 0 atom garbage collections which collected 0 bytes
|
||
0.880 sec. runtime
|
||
1.020 sec. cputime
|
||
25.055 sec. elapsed time
|
||
|
||
@end example
|
||
The example shows how much memory the system spends. Memory is divided
|
||
into Program Space, Stack Space and Trail. In the example we have 3MB
|
||
allocated for program spaces, with less than half being actually
|
||
used. Yap also shows the maximum amount of heap space having been used
|
||
which was over 2MB.
|
||
|
||
The stack space is divided into two stacks which grow against each
|
||
other. We are in the top level so very little stack is being used. On
|
||
the other hand, the system did use a lot of global and local stack
|
||
during the previous execution (we refer the reader to a WAM tutorial in
|
||
order to understand what are the global and local stacks).
|
||
|
||
Yap also shows information on how many memory overflows and garbage
|
||
collections the system executed, and statistics on total execution
|
||
time. Cputime includes all running time, runtime excludes garbage
|
||
collection and stack overflow time.
|
||
|
||
@item statistics(?@var{Param},-@var{Info})
|
||
@findex statistics/2
|
||
@saindex statistics/2
|
||
@cnindex statistics/2
|
||
Gives statistical information on the system parameter given by first
|
||
argument:
|
||
|
||
@table @code
|
||
|
||
@item cputime
|
||
@findex cputime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Cputime}]}
|
||
@*
|
||
This gives the total cputime in milliseconds spent executing Prolog code,
|
||
garbage collection and stack shifts time included.
|
||
|
||
@item garbage_collection
|
||
@findex garbage_collection (statistics/2 option)
|
||
@code{[@var{Number of GCs},@var{Total Global Recovered},@var{Total Time
|
||
Spent}]}
|
||
@*
|
||
Number of garbage collections, amount of space recovered in kbytes, and
|
||
total time spent doing garbage collection in milliseconds. More detailed
|
||
information is available using @code{yap_flag(gc_trace,verbose)}.
|
||
|
||
@item global_stack
|
||
@findex global_stack (statistics/2 option)
|
||
@code{[@var{Global Stack Used},@var{Execution Stack Free}]}
|
||
@*
|
||
Space in kbytes currently used in the global stack, and space available for
|
||
expansion by the local and global stacks.
|
||
|
||
@item local_stack
|
||
@findex local_stack (statistics/2 option)
|
||
@code{[@var{Local Stack Used},@var{Execution Stack Free}]}
|
||
@*
|
||
Space in kbytes currently used in the local stack, and space available for
|
||
expansion by the local and global stacks.
|
||
|
||
@item heap
|
||
@findex heap (statistics/2 option)
|
||
@code{[@var{Heap Used},@var{Heap Free}]}
|
||
@*
|
||
Total space in kbytes not recoverable
|
||
in backtracking. It includes the program code, internal data base, and,
|
||
atom symbol table.
|
||
|
||
@item program
|
||
@findex program (statistics/2 option)
|
||
@code{[@var{Program Space Used},@var{Program Space Free}]}
|
||
@*
|
||
Equivalent to @code{heap}.
|
||
|
||
@item runtime
|
||
@findex runtime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Runtime}]}
|
||
@*
|
||
This gives the total cputime in milliseconds spent executing Prolog
|
||
code, not including garbage collections and stack shifts. Note that
|
||
until Yap4.1.2 the @code{runtime} statistics would return time spent on
|
||
garbage collection and stack shifting.
|
||
|
||
@item stack_shifts
|
||
@findex stack_shifts (stack_shifts/3 option)
|
||
@code{[@var{Number of Heap Shifts},@var{Number of Stack
|
||
Shifts},@var{Number of Trail Shifts}]}
|
||
@*
|
||
Number of times YAP had to
|
||
expand the heap, the stacks, or the trail. More detailed information is
|
||
available using @code{yap_flag(gc_trace,verbose)}.
|
||
|
||
@item trail
|
||
@findex trail (statistics/2 option)
|
||
@code{[@var{Trail Used},@var{Trail Free}]}
|
||
@*
|
||
Space in kbytes currently being used and still available for the trail.
|
||
|
||
@item walltime
|
||
@findex walltime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Runtime}]}
|
||
@*
|
||
This gives the clock time in milliseconds since starting Prolog.
|
||
|
||
@end table
|
||
|
||
@item yap_flag(?@var{Param},?@var{Value})
|
||
@findex yap_flag/2
|
||
@snindex yap_flag/2
|
||
@cnindex yap_flag/2
|
||
Set or read system properties for @var{Param}:
|
||
|
||
@table @code
|
||
|
||
@item argv
|
||
@findex argv (yap_flag/2 option)
|
||
@* Read-only flag. It unifies with a list of atoms that gives the
|
||
arguments to Yap after @code{--}.
|
||
|
||
@item bounded [ISO]
|
||
@findex bounded (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling whether integers are bounded. The value depends
|
||
on whether YAP uses the GMP library or not.
|
||
|
||
@item profiling
|
||
@findex call_counting (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) do not compile call counting information for
|
||
procedures. If @code{on} compile predicates so that they calls and
|
||
retries to the predicate may be counted. Profiling data can be read through the
|
||
@code{call_count_data/3} built-in.
|
||
|
||
@item char_conversion [ISO]
|
||
@findex char_conversion (yap_flag/2 option)
|
||
@*
|
||
Writable flag telling whether a character conversion table is used when
|
||
reading terms. The default value for this flag is @code{off} except in
|
||
@code{sicstus} and @code{iso} language modes, where it is @code{on}.
|
||
|
||
@item character_escapes [ISO]
|
||
@findex character_escapes (yap_flag/2 option)
|
||
@* Writable flag telling whether a character escapes are enables,
|
||
@code{on}, or disabled, @code{off}. The default value for this flag is
|
||
@code{on}.
|
||
|
||
@c You can also use @code{cprolog} mode, which corresponds to @code{off},
|
||
@c @code{iso} mode, which corresponds to @code{on}, and @code{sicstus}
|
||
@c mode, which corresponds to the mode traditionally used in SICStus
|
||
@c Prolog. In this mode back-quoted escape sequences should not close with
|
||
@c a backquote and unrecognized escape codes do not result in error.
|
||
|
||
@item debug [ISO]
|
||
@findex debug (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether debugging is @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable debugging, and if
|
||
it is bound to @code{off} disable debugging.
|
||
|
||
+@item debugger_print_options
|
||
@findex debugger_print_options (yap_flag/2 option)
|
||
@*
|
||
If bound, set the argument to the @code{write_term/3} options the
|
||
debugger uses to write terms. If unbound, show the current options.
|
||
|
||
@item discontiguous_warnings
|
||
@findex discontiguous_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for discontiguous
|
||
predicates are @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable these warnings,
|
||
and if it is bound to @code{off} disable them. The default for YAP is
|
||
@code{off}, unless we are in @code{sicstus} or @code{iso} mode.
|
||
|
||
@item dollar_as_lower_case
|
||
@findex dollar_as_lower_case (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) consider the character '$' a control character, if
|
||
@code{on} consider '$' a lower case character.
|
||
|
||
@item double_quotes [ISO]
|
||
@findex double_quotes (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether a double quoted list of characters
|
||
token is converted to a list of atoms, @code{chars}, to a list of integers,
|
||
@code{codes}, or to a single atom, @code{atom}. If @var{Value} is bound, set to
|
||
the corresponding behavior. The default value is @code{codes}.
|
||
|
||
@item fast
|
||
@findex fast (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow fast machine code, if @code{off} (default) disable it. Only
|
||
available in experimental implementations.
|
||
|
||
@item fileerrors
|
||
@findex fileerrors (yap_flag/2 option)
|
||
@*
|
||
If @code{on} @code{fileerrors} is @code{on}, if @code{off} (default)
|
||
@code{fileerrors} is disabled.
|
||
|
||
@item float_format
|
||
@findex float_format (yap_flag/2 option)
|
||
@* C-library @code{printf()} format specification used by @code{write/1} and
|
||
friends to determine how floating point numbers are printed. The
|
||
default is @code{%.15g}. The specified value is passed to @code{printf()}
|
||
without further checking. For example, if you want less digits
|
||
printed, @code{%g} will print all floats using 6 digits instead of the
|
||
default 15.
|
||
|
||
@item gc
|
||
@findex gc (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow garbage collection (default), if @code{off} disable it.
|
||
|
||
@item gc_margin
|
||
@findex gc_margin (yap_flag/2 option)
|
||
@*
|
||
Set or show the minimum free stack before starting garbage
|
||
collection. The default depends on total stack size.
|
||
|
||
@item gc_trace
|
||
@findex gc_trace (yap_flag/2 option)
|
||
@* If @code{off} (default) do not show information on garbage collection
|
||
and stack shifts, if @code{on} inform when a garbage collection or stack
|
||
shift happened, if @code{verbose} give detailed information on garbage
|
||
collection and stack shifts. Last, if @code{very_verbose} give detailed
|
||
information on data-structures found during the garbage collection
|
||
process, namely, on choice-points.
|
||
|
||
@item host_type
|
||
@findex host_type (yap_flag/2 option)
|
||
@* Return @code{configure} system information, including the machine-id
|
||
for which Yap was compiled and Operating System information.
|
||
|
||
@item index
|
||
@findex index (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow indexing (default), if @code{off} disable it.
|
||
|
||
@item informational_messages
|
||
@findex informational_messages (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow printing of informational messages, such as the ones
|
||
that are printed when consulting. If @code{off} disable printing
|
||
these messages. It is @code{on} by default except if Yap is booted with
|
||
the @code{-L} flag.
|
||
|
||
@item integer_rounding_function [ISO]
|
||
@findex integer_rounding_function (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the rounding function used for integers. Takes the value
|
||
@code{down} for the current version of YAP.
|
||
|
||
@item language
|
||
@findex language (yap_flag/2 option)
|
||
@*
|
||
Choose whether YAP is closer to C-Prolog, @code{cprolog}, iso-prolog,
|
||
@code{iso} or SICStus Prolog, @code{sicstus}. The current default is
|
||
@code{cprolog}. This flag affects update semantics, leashing mode,
|
||
style_checking, handling calls to undefined procedures, how directives
|
||
are interpreted, when to use dynamic, character escapes, and how files
|
||
are consulted.
|
||
|
||
@item max_arity [ISO]
|
||
@findex max_arity (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the maximum arity of a functor. Takes the value
|
||
@code{unbounded} for the current version of YAP.
|
||
|
||
@item max_integer [ISO]
|
||
@findex max_integer (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the maximum integer in the
|
||
implementation. Depends on machine and Operating System
|
||
architecture, and on whether YAP uses the @code{GMP} multi-precision
|
||
library. If @code{bounded} is false, requests for @code{max_integer}
|
||
will fail.
|
||
|
||
@item max_tagged_integer
|
||
@findex max_tagged_integer (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the maximum integer we can store as a single
|
||
word. Depends on machine and Operating System
|
||
architecture. It can be used to find the word size of the current machine.
|
||
|
||
@item min_integer [ISO]
|
||
@findex min_integer (yap_flag/2 option)
|
||
@* Read-only flag telling the minimum integer in the
|
||
implementation. Depends on machine and Operating System architecture,
|
||
and on whether YAP uses the @code{GMP} multi-precision library. If
|
||
@code{bounded} is false, requests for @code{min_integer} will fail.
|
||
|
||
@item min_tagged_integer
|
||
@findex max_tagged_integer (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the minimum integer we can store as a single
|
||
word. Depends on machine and Operating System
|
||
architecture.
|
||
|
||
@item n_of_integer_keys_in_bb
|
||
@findex n_of_integer_keys_in_bb (yap_flag/2 option)
|
||
@*
|
||
Read or set the size of the hash table that is used for looking up the
|
||
blackboard when the key is an integer.
|
||
|
||
@item n_of_integer_keys_in_db
|
||
@findex n_of_integer_keys_in_db (yap_flag/2 option)
|
||
@*
|
||
Read or set the size of the hash table that is used for looking up the
|
||
internal data-base when the key is an integer.
|
||
|
||
@item profiling
|
||
@findex profiling (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) do not compile profiling information for
|
||
procedures. If @code{on} compile predicates so that they will output
|
||
profiling information. Profiling data can be read through the
|
||
@code{profile_data/3} built-in.
|
||
|
||
@item redefine_warnings
|
||
@findex discontiguous_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for procedures defined
|
||
in several different files are @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable these warnings,
|
||
and if it is bound to @code{off} disable them. The default for YAP is
|
||
@code{off}, unless we are in @code{sicstus} or @code{iso} mode.
|
||
|
||
@item single_var_warnings
|
||
@findex single_var_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for singleton variables
|
||
are @code{on} or @code{off}. If @var{Value} is bound to @code{on} enable
|
||
these warnings, and if it is bound to @code{off} disable them. The
|
||
default for YAP is @code{off}, unless we are in @code{sicstus} or
|
||
@code{iso} mode.
|
||
|
||
@item strict_iso
|
||
@findex strict_iso (prolog_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether strict ISO compatibility mode
|
||
is @code{on} or @code{off}. If @var{Value} is bound to @code{on} set
|
||
language mode to @code{iso} and enable strict mode. If @var{Value} is
|
||
bound to @code{off} disable strict mode, and keep the current language
|
||
mode. The default for YAP is @code{off}.
|
||
|
||
Under strict ISO prolog mode all calls to non-ISO built-ins generate an
|
||
error. Compilation of clauses that would call non-ISO built-ins will
|
||
also generate errors. Pre-processing for grammar rules is also
|
||
disabled. Module expansion is still performed.
|
||
|
||
Arguably, ISO Prolog does not provide all the functionality required
|
||
from a modern Prolog system. Moreover, because most Prolog
|
||
implementations do not fully implement the standard and because the
|
||
standard itself gives the implementor latitude in a few important
|
||
questions, such as the unification algorithm and maximum size for
|
||
numbers there is not guarantee that programs compliant with this mode
|
||
will work the same way in every Prolog and in every platform. We thus
|
||
believe this mode is mostly useful when investigating how a program
|
||
depends on a Prolog's platform specific features.
|
||
|
||
@item stack_dump_on_error
|
||
@findex stack_dump_on_error (yap_flag/2 option)
|
||
@*
|
||
If @code{on} show a stack dump when Yap finds an error. The default is
|
||
@code{off}.
|
||
|
||
@item syntax_errors
|
||
@findex syntax_errors (yap_flag/2 option)
|
||
@*
|
||
Control action to be taken after syntax errors while executing @code{read/1},
|
||
@code{read/2}, or @code{read_term/3}:
|
||
@table @code
|
||
|
||
@item dec10
|
||
@*
|
||
Report the syntax error and retry reading the term.
|
||
|
||
@item fail
|
||
@*
|
||
Report the syntax error and fail (default).
|
||
|
||
@item error
|
||
@*
|
||
Report the syntax error and generate an error.
|
||
|
||
@item quiet
|
||
@*
|
||
Just fail
|
||
@end table
|
||
|
||
@item system_options
|
||
@findex system_options (yap_flag/2 option)
|
||
@* This read only flag tells which options were used to compile
|
||
Yap. Currently it informs whether the system supports
|
||
@code{coroutining}, @code{depth_limit}, the @code{low_level_tracer},
|
||
@code{or-parallelism}, @code{rational_trees}, @code{tabling},
|
||
@code{threads}, or the @code{wam_profiler}.
|
||
|
||
@item tabling_mode
|
||
@* Sets or reads the tabling mode for all tabled predicates. Please
|
||
@pxref{Tabling} for the list of options.
|
||
|
||
@item to_chars_mode
|
||
@findex to_chars_modes (yap_flag/2 option)
|
||
@* Define whether YAP should follow @code{quintus}-like
|
||
semantics for the @code{atom_chars/1} or @code{number_chars/1} built-in,
|
||
or whether it should follow the ISO standard (@code{iso} option).
|
||
|
||
+@item toplevel_hook
|
||
@findex toplevel_hook (yap_flag/2 option)
|
||
@*
|
||
+If bound, set the argument to a goal to be executed before entering the
|
||
top-level. If unbound show the current goal or @code{true} if none is
|
||
presented. Only the first solution is considered and the goal is not
|
||
backtracked into.
|
||
|
||
+@item toplevel_print_options
|
||
@findex toplevel_print_options (yap_flag/2 option)
|
||
@*
|
||
+If bound, set the argument to the @code{write_term/3} options used to write
|
||
terms from the top-level. If unbound, show the current options.
|
||
|
||
@item typein_module
|
||
@findex typein_module (yap_flag/2 option)
|
||
@*
|
||
If bound, set the current working or type-in module to the argument,
|
||
which must be an atom. If unbound, unify the argument with the current
|
||
working module.
|
||
|
||
@item unknown [ISO]
|
||
@findex unknown (yap_flag/2 option)
|
||
@*
|
||
Corresponds to calling the @code{unknown/2} built-in.
|
||
|
||
@item update_semantics
|
||
@findex update_semantics (yap_flag/2 option)
|
||
@*
|
||
Define whether YAP should follow @code{immediate} update
|
||
semantics, as in C-Prolog (default), @code{logical} update semantics,
|
||
as in Quintus Prolog, SICStus Prolog, or in the ISO standard. There is
|
||
also an intermediate mode, @code{logical_assert}, where dynamic
|
||
procedures follow logical semantics but the internal data base still
|
||
follows immediate semantics.
|
||
|
||
@item user_error
|
||
@findex user_error (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_error} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_error} stream.
|
||
|
||
By default, the @code{user_error} stream is set to a stream
|
||
corresponding to the Unix @code{stderr} stream.
|
||
|
||
The next example shows how to use this flag:
|
||
@example
|
||
?- open( '/dev/null', append, Error,
|
||
[alias(mauri_tripa)] ).
|
||
|
||
Error = '$stream'(3) ? ;
|
||
|
||
no
|
||
?- set_prolog_flag(user_error, mauri_tripa).
|
||
|
||
close(mauri_tripa).
|
||
|
||
yes
|
||
?-
|
||
@end example
|
||
We execute three commands. First, we open a stream in write mode and
|
||
give it an alias, in this case @code{mauri_tripa}. Next, we set
|
||
@code{user_error} to the stream via the alias. Note that after we did so
|
||
prompts from the system were redirected to the stream
|
||
@code{mauri_tripa}. Last, we close the stream. At this point, YAP
|
||
automatically redirects the @code{user_error} alias to the original
|
||
@code{stderr}.
|
||
|
||
@item user_input
|
||
@findex user_input (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_input} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_input} stream.
|
||
|
||
By default, the @code{user_input} stream is set to a stream
|
||
corresponding to the Unix @code{stdin} stream.
|
||
|
||
@item user_output
|
||
@findex user_output (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_output} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_output} stream.
|
||
|
||
By default, the @code{user_output} stream is set to a stream
|
||
corresponding to the Unix @code{stdout} stream.
|
||
|
||
@item version
|
||
@findex version (yap_flag/2 option)
|
||
@*
|
||
Read-only flag that giving the current version of Yap.
|
||
|
||
@item write_strings
|
||
@findex write_strings (yap_flag/2 option)
|
||
@* Writable flag telling whether the system should write lists of
|
||
integers that are writable character codes using the list notation. It
|
||
is @code{on} if enables or @code{off} if disabled. The default value for
|
||
this flag is @code{off}.
|
||
|
||
@end table
|
||
|
||
@item current_prolog_flag(?@var{Flag},-@var{Value}) [ISO]
|
||
@findex current_prolog_flag/2
|
||
@snindex current_prolog_flag/2
|
||
@cnindex current_prolog_flag/2
|
||
|
||
Obtain the value for a YAP Prolog flag. Equivalent to calling
|
||
@code{yap_flag/2} with the second argument unbound, and unifying the
|
||
returned second argument with @var{Value}.
|
||
|
||
@item prolog_flag(?@var{Flag},-@var{OldValue},+@var{NewValue})
|
||
@findex prolog_flag/3
|
||
@syindex prolog_flag/3
|
||
@cnindex prolog_flag/3
|
||
|
||
Obtain the value for a YAP Prolog flag and then set it to a new
|
||
value. Equivalent to first calling @code{current_prolog_flag/2} with the
|
||
second argument @var{OldValue} unbound and then calling
|
||
@code{set_prolog_flag/2} with the third argument @var{NewValue}.
|
||
|
||
@item set_prolog_flag(+@var{Flag},+@var{Value}) [ISO]
|
||
@findex set_prolog_flag/2
|
||
@snindex set_prolog_flag/2
|
||
@cnindex set_prolog_flag/2
|
||
|
||
Set the value for YAP Prolog flag @code{Flag}. Equivalent to
|
||
calling @code{yap_flag/2} with both arguments bound.
|
||
|
||
@item op(+@var{P},+@var{T},+@var{A}) [ISO]
|
||
@findex op/3
|
||
@syindex op/3
|
||
@cyindex op/3
|
||
Defines the operator @var{A} or the list of operators @var{A} with type
|
||
@var{T} (which must be one of @code{xfx}, @code{xfy},@code{yfx},
|
||
@code{xf}, @code{yf}, @code{fx} or @code{fy}) and precedence @var{P}
|
||
(see appendix iv for a list of predefined operators).
|
||
|
||
Note that if there is a preexisting operator with the same name and
|
||
type, this operator will be discarded. Also, @code{','} may not be defined
|
||
as an operator, and it is not allowed to have the same for an infix and
|
||
a postfix operator.
|
||
|
||
@item current_op(@var{P},@var{T},@var{F}) [ISO]
|
||
@findex current_op/3
|
||
@syindex current_op/3
|
||
@cnindex current_op/3
|
||
Defines the relation: @var{P} is a currently defined operator of type
|
||
@var{T} and precedence @var{P}.
|
||
|
||
@item prompt(-@var{A},+@var{B})
|
||
@findex prompt/2
|
||
@syindex prompt/2
|
||
@cyindex prompt/2
|
||
Changes YAP input prompt from @var{A} to @var{B}.
|
||
|
||
@item initialization
|
||
@findex initialization/0
|
||
@syindex initialization/0
|
||
@cnindex initialization/0
|
||
Execute the goals defined by initialization/1. Only the first answer is
|
||
considered.
|
||
|
||
@item prolog_initialization(@var{G})
|
||
@findex prolog_initialization/1
|
||
@saindex prolog_initialization/1
|
||
@cnindex prolog_initialization/1
|
||
Add a goal to be executed on system initialization. This is compatible
|
||
with SICStus Prolog's @code{initialization/1}.
|
||
|
||
@item version
|
||
@findex version/0
|
||
@saindex version/0
|
||
@cnindex version/0
|
||
Write YAP's boot message.
|
||
|
||
@item version(-@var{Message})
|
||
@findex version/1
|
||
@syindex version/1
|
||
@cnindex version/1
|
||
Add a message to be written when yap boots or after aborting. It is not
|
||
possible to remove messages.
|
||
|
||
@item prolog_load_context(?@var{Key}, ?@var{Value})
|
||
@findex prolog_load_context/2
|
||
@syindex prolog_load_context/2
|
||
@cnindex prolog_load_context/2
|
||
Obtain information on what is going on in the compilation process. The
|
||
following keys are available:
|
||
|
||
@table @code
|
||
|
||
@item directory
|
||
@findex directory (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the directory where YAP is currently consulting the
|
||
file.
|
||
|
||
@item file
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the file currently being consulted. Notice that included
|
||
filed are ignored.
|
||
|
||
@item module
|
||
@findex module (prolog_load_context/2 option)
|
||
@*
|
||
Current source module.
|
||
|
||
@item source
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the file currently being read in, which may be consulted,
|
||
reconsulted, or included.
|
||
|
||
@item stream
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Stream currently being read in.
|
||
|
||
@item term_position
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Stream position at the stream currently being read in.
|
||
@end table
|
||
|
||
|
||
@end table
|
||
|
||
@node Library, SWI-Prolog, Builtins, Top
|
||
|
||
@chapter Library Predicates
|
||
|
||
Library files reside in the library_directory path (set by the
|
||
@code{LIBDIR} variable in the Makefile for YAP). Currently,
|
||
most files in the library are from the Edinburgh Prolog library.
|
||
|
||
@menu
|
||
|
||
Library, Extensions, Builtins, Top
|
||
* Apply Macros:: Apply a Predicate to a list or to sub-terms.
|
||
* Association Lists:: Binary Tree Implementation of Association Lists.
|
||
* AVL Trees:: Predicates to add and lookup balanced binary trees.
|
||
* Heaps:: Labelled binary tree where the key of each node is less
|
||
than or equal to the keys of its children.
|
||
* Lists:: List Manipulation
|
||
* Ordered Sets:: Ordered Set Manipulation
|
||
* Pseudo Random:: Pseudo Random Numbers
|
||
* Queues:: Queue Manipulation
|
||
* Random:: Random Numbers
|
||
* Read Utilities:: SWI inspired utilities for fast stream scanning.
|
||
* Red-Black Trees:: Predicates to add, lookup and delete in red-black binary trees.
|
||
* RegExp:: Regular Expression Manipulation
|
||
* Splay Trees:: Splay Trees
|
||
* String I/O:: Writing To and Reading From Strings
|
||
* System:: System Utilities
|
||
* Terms:: Utilities on Terms
|
||
* Cleanup:: Call With registered Cleanup Calls
|
||
* Timeout:: Call With Timeout
|
||
* Trees:: Updatable Binary Trees
|
||
* UGraphs:: Unweighted Graphs
|
||
* DGraphs:: Directed Graphs Implemented With Red-Black Trees
|
||
* UnDGraphs:: Undirected Graphs Using DGraphs
|
||
* LAM:: LAM MPI
|
||
|
||
|
||
@end menu
|
||
|
||
|
||
@node Apply Macros, Association Lists, , Library
|
||
@section Apply Macros
|
||
@cindex macros
|
||
|
||
This library provides a set of utilities for applying a predicate to
|
||
all elements of a list or to all sub-terms of a term. They allow to
|
||
easily perform the most common do-loop constructs in Prolog. To avoid
|
||
performance degradation due to apply/2, each call creates an
|
||
equivalent Prolog program, without meta-calls, which is executed by
|
||
the Prolog engine instead. Note that if the equivalent Prolog program
|
||
already exists, it will be simply used. The library is based on code
|
||
by Joachim Schimpf.
|
||
|
||
The following routines are available once included with the
|
||
@code{use_module(library(apply_macros))} command.
|
||
|
||
@table @code
|
||
@item maplist(+@var{Pred}, ?@var{ListIn}, ?@var{ListOut})
|
||
@findex maplist/3
|
||
@snindex maplist/3
|
||
@cnindex maplist/3
|
||
Creates @var{ListOut} by applying the predicate @var{Pred} to all
|
||
elements of @var{ListIn}.
|
||
|
||
@item checklist(+@var{Pred}, +@var{List})
|
||
@findex checklist/2
|
||
@snindex checklist/2
|
||
@cnindex checklist/2
|
||
Succeeds if the predicate @var{Pred} succeeds on all elements of @var{List}.
|
||
|
||
@item selectlist(+@var{Pred}, +@var{ListIn}, ?@var{ListOut})
|
||
@findex selectlist/3
|
||
@snindex selectlist/3
|
||
@cnindex selectlist/3
|
||
Creates @var{ListOut} of all list elements of @var{ListIn} that pass a given test
|
||
|
||
@item convlist(+@var{Pred}, +@var{ListIn}, ?@var{ListOut})
|
||
@findex convlist/3
|
||
@snindex convlist/3
|
||
@cnindex convlist/3
|
||
A combination of @code{maplist} and @code{selectlist}: creates @var{ListOut} by
|
||
applying the predicate @var{Pred} to all list elements on which
|
||
@var{Pred} succeeds
|
||
|
||
@item sumlist(+@var{Pred}, +@var{List}, ?@var{AccIn}, ?@var{AccOut})
|
||
@findex sumlist/4
|
||
@snindex sumlist/4
|
||
@cnindex sumlist/4
|
||
Calls @var{Pred} on all elements of List and collects a result in
|
||
@var{Accumulator}.
|
||
|
||
@item mapargs(+@var{Pred}, ?@var{TermIn}, ?@var{TermOut})
|
||
@findex mapargs/3
|
||
@snindex mapargs/3
|
||
@cnindex mapargs/3
|
||
Creates @var{TermOut} by applying the predicate @var{Pred} to all
|
||
arguments of @var{TermIn}
|
||
|
||
@item sumargs(+@var{Pred}, +@var{Term}, ?@var{AccIn}, ?@var{AccOut})
|
||
@findex sumargs/4
|
||
@snindex sumargs/4
|
||
@cnindex sumargs/4
|
||
Calls the predicate @var{Pred} on all arguments of @var{Term} and
|
||
collects a result in @var{Accumulator}
|
||
|
||
@item mapnodes(+@var{Pred}, +@var{TermIn}, ?@var{TermOut})
|
||
@findex mapnodes/3
|
||
@snindex mapnodes/3
|
||
@cnindex mapnodes/3
|
||
Creates @var{TermOut} by applying the predicate @var{Pred}
|
||
to all sub-terms of @var{TermIn} (depth-first and left-to-right order)
|
||
|
||
@item checknodes(+@var{Pred}, +@var{Term})
|
||
@findex checknodes/3
|
||
@snindex checknodes/3
|
||
@cnindex checknodes/3
|
||
Succeeds if the predicate @var{Pred} succeeds on all sub-terms of
|
||
@var{Term} (depth-first and left-to-right order)
|
||
|
||
@item sumnodes(+@var{Pred}, +@var{Term}, ?@var{AccIn}, ?@var{AccOut})
|
||
@findex sumnodes/4
|
||
@snindex sumnodes/4
|
||
@cnindex sumnodes/4
|
||
Calls the predicate @var{Pred} on all sub-terms of @var{Term} and
|
||
collect a result in @var{Accumulator} (depth-first and left-to-right order)
|
||
@end table
|
||
|
||
Examples:
|
||
|
||
@example
|
||
%given
|
||
plus(X,Y,Z) :- Z is X + Y.
|
||
plus_if_pos(X,Y,Z) :- Y > 0, Z is X + Y.
|
||
vars(X, Y, [X|Y]) :- var(X), !.
|
||
vars(_, Y, Y).
|
||
trans(TermIn, TermOut) :-
|
||
(compound(TermIn) ; atom(TermIn)),
|
||
TermIn =.. [p|Args],
|
||
TermOut =..[q|Args],
|
||
!.
|
||
trans(X,X).
|
||
|
||
%success
|
||
|
||
maplist(plus(1), [1,2,3,4], [2,3,4,5]).
|
||
checklist(var, [X,Y,Z]).
|
||
selectlist(<(0), [-1,0,1], [1]).
|
||
convlist(plus_if_pos(1), [-1,0,1], [2]).
|
||
sumlist(plus, [1,2,3,4], 1, 11).
|
||
mapargs(number_atom,s(1,2,3), s('1','2','3')).
|
||
sumargs(vars, s(1,X,2,Y), [], [Y,X]).
|
||
mapnodes(trans, p(a,p(b,a),c), q(a,q(b,a),c)).
|
||
checknodes(\==(T), p(X,p(Y,X),Z)).
|
||
sumnodes(vars, [c(X), p(X,Y), q(Y)], [], [Y,Y,X,X]).
|
||
% another one
|
||
maplist(mapargs(number_atom),[c(1),s(1,2,3)],[c('1'),s('1','2','3')]).
|
||
@end example
|
||
|
||
|
||
@node Association Lists, AVL Trees, Apply Macros, Library
|
||
@section Association Lists
|
||
@cindex association list
|
||
|
||
The following association list manipulation predicates are available
|
||
once included with the @code{use_module(library(assoc))} command. The
|
||
original library used Richard O'Keefe's implementation, on top of
|
||
unbalanced binary trees. The current code utilises code from the
|
||
red-black trees library and emulates the SICStus Prolog interface.
|
||
|
||
@table @code
|
||
@item assoc_to_list(+@var{Assoc},?@var{List})
|
||
@findex assoc_to_list/2
|
||
@syindex assoc_to_list/2
|
||
@cnindex assoc_to_list/2
|
||
Given an association list @var{Assoc} unify @var{List} with a list of
|
||
the form @var{Key-Val}, where the elements @var{Key} are in ascending
|
||
order.
|
||
|
||
@item del_assoc(+@var{Key}, +@var{Assoc}, ?@var{Val}, ?@var{NewAssoc})
|
||
@findex del_assoc/4
|
||
@syindex del_assoc/4
|
||
@cnindex del_assoc/4
|
||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||
the element with @var{Key} and @var{Val} from the list @var{Assoc}.
|
||
|
||
@item del_max_assoc(+@var{Assoc}, ?@var{Key}, ?@var{Val}, ?@var{NewAssoc})
|
||
@findex del_max_assoc/4
|
||
@syindex del_max_assoc/4
|
||
@cnindex del_max_assoc/4
|
||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||
the largest element of the list, with @var{Key} and @var{Val} from the
|
||
list @var{Assoc}.
|
||
|
||
@item del_min_assoc(+@var{Assoc}, ?@var{Key}, ?@var{Val}, ?@var{NewAssoc})
|
||
@findex del_min_assoc/4
|
||
@syindex del_min_assoc/4
|
||
@cnindex del_min_assoc/4
|
||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||
the smallest element of the list, with @var{Key} and @var{Val}
|
||
from the list @var{Assoc}.
|
||
|
||
@item empty_assoc(+@var{Assoc})
|
||
@findex empty_assoc/1
|
||
@syindex empty_assoc/1
|
||
@cnindex empty_assoc/1
|
||
Succeeds if association list @var{Assoc} is empty.
|
||
|
||
@item gen_assoc(+@var{Assoc},?@var{Key},?@var{Value})
|
||
@findex gen_assoc/3
|
||
@syindex gen_assoc/3
|
||
@cnindex gen_assoc/3
|
||
Given the association list @var{Assoc}, unify @var{Key} and @var{Value}
|
||
with two associated elements. It can be used to enumerate all elements
|
||
in the association list.
|
||
|
||
@item get_assoc(+@var{Key},+@var{Assoc},?@var{Value})
|
||
@findex get_next_assoc/4
|
||
@syindex get_next_assoc/4
|
||
@cnindex get_next_assoc/4
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the associated value.
|
||
|
||
@item get_assoc(+@var{Key},+@var{Assoc},?@var{Value},+@var{NAssoc},?@var{NValue})
|
||
@findex get_assoc/5
|
||
@syindex get_assoc/5
|
||
@cnindex get_assoc/5
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the associated value @var{Value} and a new association list
|
||
@var{NAssoc} where @var{Key} is associated with @var{NValue}.
|
||
|
||
@item get_prev_assoc(+@var{Key},+@var{Assoc},?@var{Next},?@var{Value})
|
||
@findex get_prev_assoc/4
|
||
@syindex get_prev_assoc/4
|
||
@cnindex get_prev_assoc/4
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the previous key, @var{Next}, and its value, @var{Value}.
|
||
|
||
@item get_next_assoc(+@var{Key},+@var{Assoc},?@var{Next},?@var{Value})
|
||
@findex get_assoc/3
|
||
@syindex get_assoc/3
|
||
@cnindex get_assoc/3
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the next key, @var{Next}, and its value, @var{Value}.
|
||
|
||
@item is_assoc(+@var{Assoc})
|
||
@findex is_assoc/1
|
||
@syindex is_assoc/1
|
||
@cnindex is_assoc/1
|
||
Succeeds if @var{Assoc} is an association list, that is, if it is a
|
||
red-black tree.
|
||
|
||
@item list_to_assoc(+@var{List},?@var{Assoc})
|
||
@findex list_to_assoc/2
|
||
@syindex list_to_assoc/2
|
||
@cnindex list_to_assoc/2
|
||
Given a list @var{List} such that each element of @var{List} is of the
|
||
form @var{Key-Val}, and all the @var{Keys} are unique, @var{Assoc} is
|
||
the corresponding association list.
|
||
|
||
@item map_assoc(+@var{Pred},+@var{Assoc})
|
||
@findex map_assoc/2
|
||
@syindex map_assoc/2
|
||
@cnindex map_assoc/2
|
||
Succeeds if the unary predicate name @var{Pred}(@var{Val}) holds for every
|
||
element in the association list.
|
||
|
||
@item map_assoc(+@var{Pred},+@var{Assoc},?@var{New})
|
||
@findex map_assoc/3
|
||
@syindex map_assoc/3
|
||
@cnindex map_assoc/3
|
||
Given the binary predicate name @var{Pred} and the association list
|
||
@var{Assoc}, @var{New} in an association list with keys in @var{Assoc},
|
||
and such that if @var{Key-Val} is in @var{Assoc}, and @var{Key-Ans} is in
|
||
@var{New}, then @var{Pred}(@var{Val},@var{Ans}) holds.
|
||
|
||
@item max_assoc(+@var{Assoc},-@var{Key},?@var{Value})
|
||
@findex max_assoc/3
|
||
@syindex max_assoc/3
|
||
@cnindex max_assoc/3
|
||
Given the association list
|
||
@var{Assoc}, @var{Key} in the largest key in the list, and @var{Value}
|
||
the associated value.
|
||
|
||
@item min_assoc(+@var{Assoc},-@var{Key},?@var{Value})
|
||
@findex min_assoc/3
|
||
@syindex min_assoc/3
|
||
@cnindex min_assoc/3
|
||
Given the association list
|
||
@var{Assoc}, @var{Key} in the smallest key in the list, and @var{Value}
|
||
the associated value.
|
||
|
||
@item ord_list_to_assoc(+@var{List},?@var{Assoc})
|
||
@findex ord_list_to_assoc/2
|
||
@syindex ord_list_to_assoc/2
|
||
@cnindex ord_list_to_assoc/2
|
||
Given an ordered list @var{List} such that each element of @var{List} is
|
||
of the form @var{Key-Val}, and all the @var{Keys} are unique, @var{Assoc} is
|
||
the corresponding association list.
|
||
|
||
@item put_assoc(+@var{Key},+@var{Assoc},+@var{Val},+@var{New})
|
||
@findex put_assoc/4
|
||
@syindex put_assoc/4
|
||
@cnindex put_assoc/4
|
||
The association list @var{New} includes and element of association
|
||
@var{key} with @var{Val}, and all elements of @var{Assoc} that did not
|
||
have key @var{Key}.
|
||
|
||
@end table
|
||
|
||
@node AVL Trees, Heaps, Association Lists, Library
|
||
@section AVL Trees
|
||
@cindex AVL trees
|
||
|
||
AVL trees are balanced search binary trees. They are named after their
|
||
inventors, Adelson-Velskii and Landis, and they were the first
|
||
dynamically balanced trees to be proposed. The YAP AVL tree manipulation
|
||
predicates library uses code originally written by Martin van Emdem and
|
||
published in the Logic Programming Newsletter, Autumn 1981. A bug in
|
||
this code was fixed by Philip Vasey, in the Logic Programming
|
||
Newsletter, Summer 1982. The library currently only includes routines to
|
||
insert and lookup elements in the tree. Please try red-black trees if
|
||
you need deletion.
|
||
|
||
@table @code
|
||
@item avl_insert(+@var{Key},?@var{Value},+@var{T0},+@var{TF})
|
||
@findex avl_insert/4
|
||
@snindex avl_insert/4
|
||
@cnindex avl_insert/4
|
||
Add an element with key @var{Key} and @var{Value} to the AVL tree
|
||
@var{T0} creating a new AVL tree @var{TF}. Duplicated elements are
|
||
allowed.
|
||
|
||
@item avl_lookup(+@var{Key},-@var{Value},+@var{T})
|
||
@findex avl_lookup/3
|
||
@snindex avl_lookup/3
|
||
@cnindex avl_lookup/3
|
||
Lookup an element with key @var{Key} in the AVL tree
|
||
@var{T}, returning the value @var{Value}.
|
||
|
||
@end table
|
||
|
||
@node Heaps, Lists, AVL Trees, Library
|
||
@section Heaps
|
||
@cindex heap
|
||
|
||
A heap is a labelled binary tree where the key of each node is less than
|
||
or equal to the keys of its sons. The point of a heap is that we can
|
||
keep on adding new elements to the heap and we can keep on taking out
|
||
the minimum element. If there are N elements total, the total time is
|
||
O(NlgN). If you know all the elements in advance, you are better off
|
||
doing a merge-sort, but this file is for when you want to do say a
|
||
best-first search, and have no idea when you start how many elements
|
||
there will be, let alone what they are.
|
||
|
||
The following heap manipulation routines are available once included
|
||
with the @code{use_module(library(heaps))} command.
|
||
|
||
@table @code
|
||
|
||
@item add_to_heap(+@var{Heap},+@var{key},+@var{Datum},-@var{NewHeap})
|
||
@findex add_to_heap/4
|
||
@syindex add_to_heap/4
|
||
@cnindex add_to_heap/4
|
||
Inserts the new @var{Key-Datum} pair into the heap. The insertion is not
|
||
stable, that is, if you insert several pairs with the same @var{Key} it
|
||
is not defined which of them will come out first, and it is possible for
|
||
any of them to come out first depending on the history of the heap.
|
||
|
||
@item empty_heap(?@var{Heap})
|
||
@findex empty_heap/1
|
||
@syindex empty_heap/1
|
||
@cnindex empty_heap/1
|
||
Succeeds if @var{Heap} is an empty heap.
|
||
|
||
@item get_from_heap(+@var{Heap},-@var{key},-@var{Datum},-@var{Heap})
|
||
@findex get_from_heap/4
|
||
@syindex get_from_heap/4
|
||
@cnindex get_from_heap/4
|
||
Returns the @var{Key-Datum} pair in @var{OldHeap} with the smallest
|
||
@var{Key}, and also a @var{Heap} which is the @var{OldHeap} with that
|
||
pair deleted.
|
||
|
||
@item heap_size(+@var{Heap}, -@var{Size})
|
||
@findex heap_size/2
|
||
@syindex heap_size/2
|
||
@cnindex heap_size/2
|
||
Reports the number of elements currently in the heap.
|
||
|
||
@item heap_to_list(+@var{Heap}, -@var{List})
|
||
@findex heap_to_list/2
|
||
@syindex heap_to_list/2
|
||
@cnindex heap_to_list/2
|
||
Returns the current set of @var{Key-Datum} pairs in the @var{Heap} as a
|
||
@var{List}, sorted into ascending order of @var{Keys}.
|
||
|
||
@item list_to_heap(+@var{List}, -@var{Heap})
|
||
@findex list_to_heap/2
|
||
@syindex list_to_heap/2
|
||
@cnindex list_to_heap/2
|
||
Takes a list of @var{Key-Datum} pairs (such as keysort could be used to sort)
|
||
and forms them into a heap.
|
||
|
||
@item min_of_heap(+@var{Heap}, -@var{Key}, -@var{Datum})
|
||
@findex min_of_heap/3
|
||
@syindex min_of_heap/3
|
||
@cnindex min_of_heap/3
|
||
Returns the Key-Datum pair at the top of the heap (which is of course
|
||
the pair with the smallest Key), but does not remove it from the heap.
|
||
|
||
@item min_of_heap(+@var{Heap}, -@var{Key1}, -@var{Datum1},
|
||
-@var{Key2}, -@var{Datum2})
|
||
@findex min_of_heap/5
|
||
@syindex min_of_heap/5
|
||
@cnindex min_of_heap/5
|
||
Returns the smallest (Key1) and second smallest (Key2) pairs in the
|
||
heap, without deleting them.
|
||
@end table
|
||
|
||
@node Lists, Ordered Sets, Heaps, Library
|
||
@section List Manipulation
|
||
@cindex list manipulation
|
||
|
||
The following list manipulation routines are available once included
|
||
with the @code{use_module(library(lists))} command.
|
||
|
||
@table @code
|
||
|
||
@item append(?@var{Prefix},?@var{Suffix},?@var{Combined})
|
||
@findex append/3
|
||
@syindex append/3
|
||
@cnindex append/3
|
||
True when all three arguments are lists, and the members of
|
||
@var{Combined} are the members of @var{Prefix} followed by the members of @var{Suffix}.
|
||
It may be used to form @var{Combined} from a given @var{Prefix}, @var{Suffix} or to take
|
||
a given @var{Combined} apart.
|
||
|
||
@item delete(+@var{List}, ?@var{Element}, ?@var{Residue})
|
||
@findex delete/3
|
||
@syindex delete/3
|
||
@cnindex delete/3
|
||
True when @var{List} is a list, in which @var{Element} may or may not
|
||
occur, and @var{Residue} is a copy of @var{List} with all elements
|
||
identical to @var{Element} deleted.
|
||
|
||
@item flatten(+@var{List}, ?@var{FlattenedList})
|
||
@findex flatten/2
|
||
@syindex flatten/2
|
||
@cnindex flatten/2
|
||
Flatten a list of lists @var{List} into a single list
|
||
@var{FlattenedList}.
|
||
|
||
@example
|
||
?- flatten([[1],[2,3],[4,[5,6],7,8]],L).
|
||
|
||
L = [1,2,3,4,5,6,7,8] ? ;
|
||
|
||
no
|
||
@end example
|
||
|
||
@item is_list(+@var{List})
|
||
@findex is_list/1
|
||
@syindex is_list/1
|
||
@cnindex is_list/1
|
||
True when @var{List} is a proper list. That is, @var{List}
|
||
is bound to the empty list (nil) or a term with functor '.' and arity 2.
|
||
|
||
@item last(+@var{List},?@var{Last})
|
||
@findex last/2
|
||
@syindex last/2
|
||
@cnindex last/2
|
||
True when @var{List} is a list and @var{Last} is identical to its last element.
|
||
|
||
@item list_concat(+@var{Lists},?@var{List})
|
||
@findex list_concat/2
|
||
@snindex list_concat/2
|
||
@cnindex list_concat/2
|
||
True when @var{Lists} is a list of lists and @var{List} is the
|
||
concatenation of @var{Lists}.
|
||
|
||
@item member(?@var{Element}, ?@var{Set})
|
||
@findex member/2
|
||
@syindex member/2
|
||
@cnindex member/2
|
||
True when @var{Set} is a list, and @var{Element} occurs in it. It may be used
|
||
to test for an element or to enumerate all the elements by backtracking.
|
||
|
||
@item memberchk(+@var{Element}, +@var{Set})
|
||
@findex memberchk/2
|
||
@syindex memberchk/2
|
||
@cnindex memberchk/2
|
||
As @code{member/2}, but may only be used to test whether a known
|
||
@var{Element} occurs in a known Set. In return for this limited use, it
|
||
is more efficient when it is applicable.
|
||
|
||
@item nth0(?@var{N}, ?@var{List}, ?@var{Elem})
|
||
@findex nth0/2
|
||
@syindex nth0/2
|
||
@cnindex nth0/2
|
||
True when @var{Elem} is the Nth member of @var{List},
|
||
counting the first as element 0. (That is, throw away the first
|
||
N elements and unify @var{Elem} with the next.) It can only be used to
|
||
select a particular element given the list and index. For that
|
||
task it is more efficient than @code{member/2}
|
||
|
||
@item nth(?@var{N}, ?@var{List}, ?@var{Elem})
|
||
@findex nth/2
|
||
@syindex nth/2
|
||
@cnindex nth/2
|
||
The same as @code{nth0/3}, except that it counts from
|
||
1, that is @code{nth(1, [H|_], H)}.
|
||
|
||
@item nth0(?@var{N}, ?@var{List}, ?@var{Elem}, ?@var{Rest})
|
||
@findex nth0/4
|
||
@syindex nth0/4
|
||
@cnindex nth0/4
|
||
Unifies @var{Elem} with the Nth element of @var{List},
|
||
counting from 0, and @var{Rest} with the other elements. It can be used
|
||
to select the Nth element of @var{List} (yielding @var{Elem} and @var{Rest}), or to
|
||
insert @var{Elem} before the Nth (counting from 1) element of @var{Rest}, when
|
||
it yields @var{List}, e.g. @code{nth0(2, List, c, [a,b,d,e])} unifies List with
|
||
@code{[a,b,c,d,e]}. @code{nth/4} is the same except that it counts from 1. @code{nth0/4}
|
||
can be used to insert @var{Elem} after the Nth element of @var{Rest}.
|
||
|
||
@item nth(?@var{N}, ?@var{List}, ?@var{Elem}, ?@var{Rest})
|
||
@findex nth/4
|
||
@syindex nth/4
|
||
@cnindex nth/4
|
||
Unifies @var{Elem} with the Nth element of @var{List}, counting from 1,
|
||
and @var{Rest} with the other elements. It can be used to select the
|
||
Nth element of @var{List} (yielding @var{Elem} and @var{Rest}), or to
|
||
insert @var{Elem} before the Nth (counting from 1) element of
|
||
@var{Rest}, when it yields @var{List}, e.g. @code{nth(1, List, c,
|
||
[a,b,d,e])} unifies List with @code{[a,b,c,d,e]}. @code{nth/4}
|
||
can be used to insert @var{Elem} after the Nth element of @var{Rest}.
|
||
|
||
@item permutation(+@var{List},?@var{Perm})
|
||
@findex permutation/2
|
||
@syindex permutation/2
|
||
@cnindex permutation/2
|
||
True when @var{List} and @var{Perm} are permutations of each other.
|
||
|
||
@item remove_duplicates(+@var{List}, ?@var{Pruned})
|
||
@findex remove_duplicates/2
|
||
@syindex remove_duplicates/2
|
||
@cnindex remove_duplicates/2
|
||
Removes duplicated elements from @var{List}. Beware: if the @var{List} has
|
||
non-ground elements, the result may surprise you.
|
||
|
||
@item reverse(+@var{List}, ?@var{Reversed})
|
||
@findex reverse/2
|
||
@syindex reverse/2
|
||
@cnindex reverse/2
|
||
True when @var{List} and @var{Reversed} are lists with the same elements
|
||
but in opposite orders.
|
||
|
||
@item same_length(?@var{List1}, ?@var{List2})
|
||
@findex same_length/2
|
||
@syindex same_length/2
|
||
@cnindex same_length/2
|
||
True when @var{List1} and @var{List2} are both lists and have the same number
|
||
of elements. No relation between the values of their elements is
|
||
implied.
|
||
Modes @code{same_length(-,+)} and @code{same_length(+,-)} generate either list given
|
||
the other; mode @code{same_length(-,-)} generates two lists of the same length,
|
||
in which case the arguments will be bound to lists of length 0, 1, 2, ...
|
||
|
||
@item select(?@var{Element}, ?@var{Set}, ?@var{Residue})
|
||
@findex select/3
|
||
@syindex select/3
|
||
@cnindex select/3
|
||
True when @var{Set} is a list, @var{Element} occurs in @var{Set}, and @var{Residue} is
|
||
everything in @var{Set} except @var{Element} (things stay in the same order).
|
||
|
||
@item sublist(?@var{Sublist}, ?@var{List})
|
||
@findex sublist/2
|
||
@syindex sublist/2
|
||
@cnindex sublist/2
|
||
True when both @code{append(_,Sublist,S)} and @code{append(S,_,List)} hold.
|
||
|
||
@item suffix(?@var{Suffix}, ?@var{List})
|
||
@findex suffix/2
|
||
@syindex suffix/2
|
||
@cnindex suffix/2
|
||
Holds when @code{append(_,Suffix,List)} holds.
|
||
|
||
@item sum_list(?@var{Numbers}, ?@var{Total})
|
||
@findex sum_list/2
|
||
@syindex sum_list/2
|
||
@cnindex sum_list/2
|
||
True when @var{Numbers} is a list of numbers, and @var{Total} is their sum.
|
||
|
||
@item sumlist(?@var{Numbers}, ?@var{Total})
|
||
@findex sumlist/2
|
||
@syindex sumlist/2
|
||
@cnindex sumlist/2
|
||
True when @var{Numbers} is a list of integers, and @var{Total} is their
|
||
sum. The same as @code{sum_list/2}, please do use @code{sum_list/2}
|
||
instead.
|
||
|
||
@item max_list(?@var{Numbers}, ?@var{Max})
|
||
@findex max_list/2
|
||
@syindex max_list/2
|
||
@cnindex max_list/2
|
||
True when @var{Numbers} is a list of numbers, and @var{Max} is the maximum.
|
||
|
||
@item min_list(?@var{Numbers}, ?@var{Min})
|
||
@findex min_list/2
|
||
@syindex min_list/2
|
||
@cnindex min_list/2
|
||
True when @var{Numbers} is a list of numbers, and @var{Min} is the minimum.
|
||
|
||
@end table
|
||
|
||
@node Ordered Sets, Pseudo Random, Lists, Library
|
||
@section Ordered Sets
|
||
@cindex ordered set
|
||
|
||
The following ordered set manipulation routines are available once
|
||
included with the @code{use_module(library(ordsets))} command. An
|
||
ordered set is represented by a list having unique and ordered
|
||
elements. Output arguments are guaranteed to be ordered sets, if the
|
||
relevant inputs are. This is a slightly patched version of Richard
|
||
O'Keefe's original library.
|
||
|
||
@table @code
|
||
@item list_to_ord_set(+@var{List}, ?@var{Set})
|
||
@findex list_to_ord_set/2
|
||
@syindex list_to_ord_set/2
|
||
@cnindex list_to_ord_set/2
|
||
Holds when @var{Set} is the ordered representation of the set
|
||
represented by the unordered representation @var{List}.
|
||
|
||
@item merge(+@var{List1}, +@var{List2}, -@var{Merged})
|
||
@findex merge/3
|
||
@syindex merge/3
|
||
@cnindex merge/3
|
||
Holds when @var{Merged} is the stable merge of the two given lists.
|
||
|
||
Notice that @code{merge/3} will not remove duplicates, so merging
|
||
ordered sets will not necessarily result in an ordered set. Use
|
||
@code{ord_union/3} instead.
|
||
|
||
@item ord_add_element(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_add_element/3
|
||
@syindex ord_add_element/3
|
||
@cnindex ord_add_element/3
|
||
Inserting @var{Element} in @var{Set1} returns @var{Set2}. It should give
|
||
exactly the same result as @code{merge(Set1, [Element], Set2)}, but a
|
||
bit faster, and certainly more clearly. The same as @code{ord_insert/3}.
|
||
|
||
@item ord_del_element(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_del_element/3
|
||
@syindex ord_del_element/3
|
||
@cnindex ord_del_element/3
|
||
Removing @var{Element} from @var{Set1} returns @var{Set2}.
|
||
|
||
@item ord_disjoint(+@var{Set1}, +@var{Set2})
|
||
@findex ord_disjoint/2
|
||
@syindex ord_disjoint/2
|
||
@cnindex ord_disjoint/2
|
||
Holds when the two ordered sets have no element in common.
|
||
|
||
@item ord_member(+@var{Element}, +@var{Set})
|
||
@findex ord_member/2
|
||
@syindex ord_member/2
|
||
@cnindex ord_member/2
|
||
Holds when @var{Element} is a member of @var{Set}.
|
||
|
||
@item ord_insert(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_insert/3
|
||
@syindex ord_insert/3
|
||
@cnindex ord_insert/3
|
||
Inserting @var{Element} in @var{Set1} returns @var{Set2}. It should give
|
||
exactly the same result as @code{merge(Set1, [Element], Set2)}, but a
|
||
bit faster, and certainly more clearly. The same as @code{ord_add_element/3}.
|
||
|
||
@item ord_intersect(+@var{Set1}, +@var{Set2})
|
||
@findex ord_intersect/2
|
||
@syindex ord_intersect/2
|
||
@cnindex ord_intersect/2
|
||
Holds when the two ordered sets have at least one element in common.
|
||
|
||
@item ord_intersection(+@var{Set1}, +@var{Set2}, ?@var{Intersection})
|
||
@findex ord_intersect/3
|
||
@syindex ord_intersect/3
|
||
@cnindex ord_intersect/3
|
||
Holds when Intersection is the ordered representation of @var{Set1}
|
||
and @var{Set2}.
|
||
|
||
@item ord_intersection(+@var{Set1}, +@var{Set2}, ?@var{Intersection}, ?@var{Diff})
|
||
@findex ord_intersect/4
|
||
@syindex ord_intersect/4
|
||
@cnindex ord_intersect/4
|
||
Holds when Intersection is the ordered representation of @var{Set1}
|
||
and @var{Set2}. @var{Diff} is the difference between @var{Set2} and @var{Set1}.
|
||
|
||
@item ord_seteq(+@var{Set1}, +@var{Set2})
|
||
@findex ord_seteq/2
|
||
@syindex ord_seteq/2
|
||
@cnindex ord_seteq/2
|
||
Holds when the two arguments represent the same set.
|
||
|
||
@item ord_setproduct(+@var{Set1}, +@var{Set2}, -@var{Set})
|
||
@findex ord_setproduct/3
|
||
@syindex ord_setproduct/3
|
||
@cnindex ord_setproduct/3
|
||
If Set1 and Set2 are ordered sets, Product will be an ordered
|
||
set of x1-x2 pairs.
|
||
|
||
@item ord_subset(+@var{Set1}, +@var{Set2})
|
||
@findex ordsubset/2
|
||
@syindex ordsubset/2
|
||
@cnindex ordsubset/2
|
||
Holds when every element of the ordered set @var{Set1} appears in the
|
||
ordered set @var{Set2}.
|
||
|
||
@item ord_subtract(+@var{Set1}, +@var{Set2}, ?@var{Difference})
|
||
@findex ord_subtract/3
|
||
@syindex ord_subtract/3
|
||
@cnindex ord_subtract/3
|
||
Holds when @var{Difference} contains all and only the elements of @var{Set1}
|
||
which are not also in @var{Set2}.
|
||
|
||
@item ord_symdiff(+@var{Set1}, +@var{Set2}, ?@var{Difference})
|
||
@findex ord_symdiff/3
|
||
@syindex ord_symdiff/3
|
||
@cnindex ord_symdiff/3
|
||
Holds when @var{Difference} is the symmetric difference of @var{Set1}
|
||
and @var{Set2}.
|
||
|
||
@item ord_union(+@var{Sets}, ?@var{Union})
|
||
@findex ord_union/2
|
||
@syindex ord_union/2
|
||
@cnindex ord_union/2
|
||
Holds when @var{Union} is the union of the lists @var{Sets}.
|
||
|
||
@item ord_union(+@var{Set1}, +@var{Set2}, ?@var{Union})
|
||
@findex ord_union/3
|
||
@syindex ord_union/3
|
||
@cnindex ord_union/3
|
||
Holds when @var{Union} is the union of @var{Set1} and @var{Set2}.
|
||
|
||
@item ord_union(+@var{Set1}, +@var{Set2}, ?@var{Union}, ?@var{Diff})
|
||
@findex ord_union/4
|
||
@syindex ord_union/4
|
||
@cnindex ord_union/4
|
||
Holds when @var{Union} is the union of @var{Set1} and @var{Set2} and
|
||
@var{Diff} is the difference.
|
||
|
||
@end table
|
||
|
||
@node Pseudo Random, Queues, Ordered Sets, Library
|
||
@section Pseudo Random Number Integer Generator
|
||
@cindex pseudo random
|
||
|
||
The following routines produce random non-negative integers in the range
|
||
0 .. 2^(w-1) -1, where w is the word size available for integers, e.g.
|
||
32 for Intel machines and 64 for Alpha machines. Note that the numbers
|
||
generated by this random number generator are repeatable. This generator
|
||
was originally written by Allen Van Gelder and is based on Knuth Vol 2.
|
||
|
||
@table @code
|
||
@item rannum(-@var{I})
|
||
@findex rannum/1
|
||
@snindex rannum/1
|
||
@cnindex rannum/1
|
||
Produces a random non-negative integer @var{I} whose low bits are not
|
||
all that random, so it should be scaled to a smaller range in general.
|
||
The integer @var{I} is in the range 0 .. 2^(w-1) - 1. You can use:
|
||
@example
|
||
rannum(X) :- yap_flag(max_integer,MI), rannum(R), X is R/MI.
|
||
@end example
|
||
to obtain a floating point number uniformly distributed between 0 and 1.
|
||
|
||
@item ranstart
|
||
@findex ranstart/0
|
||
@snindex ranstart/0
|
||
@cnindex ranstart/0
|
||
Initialize the random number generator using a built-in seed. The
|
||
@code{ranstart/0} built-in is always called by the system when loading
|
||
the package.
|
||
|
||
@item ranstart(+@var{Seed})
|
||
@findex ranstart/1
|
||
@snindex ranstart/1
|
||
@cnindex ranstart/1
|
||
Initialize the random number generator with user-defined @var{Seed}. The
|
||
same @var{Seed} always produces the same sequence of numbers.
|
||
|
||
@item ranunif(+@var{Range},-@var{I})
|
||
@findex ranunif/2
|
||
@snindex ranunif/2
|
||
@cnindex ranunif/2
|
||
@code{ranunif/2} produces a uniformly distributed non-negative random
|
||
integer @var{I} over a caller-specified range @var{R}. If range is @var{R},
|
||
the result is in 0 .. @var{R}-1.
|
||
|
||
@end table
|
||
|
||
@node Queues, Random, Pseudo Random, Library
|
||
@section Queues
|
||
@cindex queue
|
||
|
||
The following queue manipulation routines are available once
|
||
included with the @code{use_module(library(queues))} command. Queues are
|
||
implemented with difference lists.
|
||
|
||
@table @code
|
||
|
||
@item make_queue(+@var{Queue})
|
||
@findex make_queue/1
|
||
@syindex make_queue/1
|
||
@cnindex make_queue/1
|
||
Creates a new empty queue. It should only be used to create a new queue.
|
||
|
||
@item join_queue(+@var{Element}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex join_queue/3
|
||
@syindex join_queue/3
|
||
@cnindex join_queue/3
|
||
Adds the new element at the end of the queue.
|
||
|
||
@item list_join_queue(+@var{List}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex list_join_queue/3
|
||
@syindex list_join_queue/3
|
||
@cnindex list_join_queue/3
|
||
Ads the new elements at the end of the queue.
|
||
|
||
@item jump_queue(+@var{Element}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex jump_queue/3
|
||
@syindex jump_queue/3
|
||
@cnindex jump_queue/3
|
||
Adds the new element at the front of the list.
|
||
|
||
@item list_jump_queue(+@var{List}, +@var{OldQueue}, +@var{NewQueue})
|
||
@findex list_jump_queue/3
|
||
@syindex list_jump_queue/3
|
||
@cnindex list_jump_queue/3
|
||
Adds all the elements of @var{List} at the front of the queue.
|
||
|
||
@item head_queue(+@var{Queue}, ?@var{Head})
|
||
@findex head_queue/2
|
||
@syindex head_queue/2
|
||
@cnindex head_queue/2
|
||
Unifies Head with the first element of the queue.
|
||
|
||
@item serve_queue(+@var{OldQueue}, +@var{Head}, -@var{NewQueue})
|
||
@findex serve_queue/3
|
||
@syindex serve_queue/3
|
||
@cnindex serve_queue/3
|
||
Removes the first element of the queue for service.
|
||
|
||
@item empty_queue(+@var{Queue})
|
||
@findex empty_queue/1
|
||
@syindex empty_queue/1
|
||
@cnindex empty_queue/1
|
||
Tests whether the queue is empty.
|
||
|
||
@item length_queue(+@var{Queue}, -@var{Length})
|
||
@findex length_queue/2
|
||
@syindex length_queue/2
|
||
@cnindex length_queue/2
|
||
Counts the number of elements currently in the queue.
|
||
|
||
@item list_to_queue(+@var{List}, -@var{Queue})
|
||
@findex list_to_queue/2
|
||
@syindex list_to_queue/2
|
||
@cnindex list_to_queue/2
|
||
Creates a new queue with the same elements as @var{List.}
|
||
|
||
@item queue_to_list(+@var{Queue}, -@var{List})
|
||
@findex queue_to_list/2
|
||
@syindex queue_to_list/2
|
||
@cnindex queue_to_list/2
|
||
Creates a new list with the same elements as @var{Queue}.
|
||
|
||
@end table
|
||
|
||
|
||
@node Random, Read Utilities, Queues, Library
|
||
@section Random Number Generator
|
||
@cindex queue
|
||
|
||
The following random number operations are included with the
|
||
@code{use_module(library(random))} command. Since Yap-4.3.19 Yap uses
|
||
the O'Keefe public-domain algorithm, based on the "Applied Statistics"
|
||
algorithm AS183.
|
||
|
||
@table @code
|
||
|
||
@item getrand(-@var{Key})
|
||
@findex getrand/1
|
||
@syindex getrand/1
|
||
@cnindex getrand/1
|
||
Unify @var{Key} with a term of the form @code{rand(X,Y,Z)} describing the
|
||
current state of the random number generator.
|
||
|
||
@item random(-@var{Number})
|
||
@findex random/1
|
||
@syindex random/1
|
||
@cnindex random/1
|
||
Unify @var{Number} with a floating-point number in the range @code{[0...1)}.
|
||
|
||
@item random(+@var{LOW}, +@var{HIGH}, -@var{NUMBER})
|
||
@findex random/3
|
||
@syindex random/3
|
||
@cnindex random/3
|
||
Unify @var{Number} with a number in the range
|
||
@code{[LOW...HIGH)}. If both @var{LOW} and @var{HIGH} are
|
||
integers then @var{NUMBER} will also be an integer, otherwise
|
||
@var{NUMBER} will be a floating-point number.
|
||
|
||
@item randseq(+@var{LENGTH}, +@var{MAX}, -@var{Numbers})
|
||
@findex randseq/3
|
||
@syindex randseq/3
|
||
@cnindex randseq/3
|
||
Unify @var{Numbers} with a list of @var{LENGTH} unique random integers
|
||
in the range @code{[1<>...@var{MAX})}.
|
||
|
||
@item randset(+@var{LENGTH}, +@var{MAX}, -@var{Numbers})
|
||
@findex randset/3
|
||
@syindex randset/3
|
||
@cnindex randset/3
|
||
Unify @var{Numbers} with an ordered list of @var{LENGTH} unique random
|
||
integers in the range @code{[1<>...@var{MAX})}.
|
||
|
||
@item setrand(+@var{Key})
|
||
@findex setrand/1
|
||
@syindex setrand/1
|
||
@cnindex setrand/1
|
||
Use a term of the form @code{rand(X,Y,Z)} to set a new state for the
|
||
random number generator. The integer @code{X} must be in the range
|
||
@code{[1...30269)}, the integer @code{Y} must be in the range
|
||
@code{[1...30307)}, and the integer @code{Z} must be in the range
|
||
@code{[1...30323)}.
|
||
|
||
@end table
|
||
|
||
@node Read Utilities, Red-Black Trees, Random, Library
|
||
@section Read Utilities
|
||
|
||
The @code{readutil} library contains primitives to read lines, files,
|
||
multiple terms, etc.
|
||
|
||
@table @code
|
||
@item read_line_to_codes(+@var{Stream}, -@var{Codes})
|
||
@findex read_line_to_codes/2
|
||
@snindex read_line_to_codes/2
|
||
@cnindex read_line_to_codes/2
|
||
|
||
Read the next line of input from @var{Stream} and unify the result with
|
||
@var{Codes} @emph{after} the line has been read. A line is ended by a
|
||
newline character or end-of-file. Unlike @code{read_line_to_codes/3},
|
||
this predicate removes trailing newline character.
|
||
|
||
On end-of-file the atom @code{end_of_file} is returned. See also
|
||
@code{at_end_of_stream/[0,1]}.
|
||
|
||
@item read_line_to_codes(+@var{Stream}, -@var{Codes}, ?@var{Tail})
|
||
@findex read_line_to_codes/3
|
||
@snindex read_line_to_codes/3
|
||
@cnindex read_line_to_codes/3
|
||
Diference-list version to read an input line to a list of character
|
||
codes. Reading stops at the newline or end-of-file character, but
|
||
unlike @code{read_line_to_codes/2}, the newline is retained in the
|
||
output. This predicate is especially useful for readine a block of
|
||
lines upto some delimiter. The following example reads an HTTP header
|
||
ended by a blank line:
|
||
|
||
@example
|
||
read_header_data(Stream, Header) :-
|
||
read_line_to_codes(Stream, Header, Tail),
|
||
read_header_data(Header, Stream, Tail).
|
||
|
||
read_header_data("\r\n", _, _) :- !.
|
||
read_header_data("\n", _, _) :- !.
|
||
read_header_data("", _, _) :- !.
|
||
read_header_data(_, Stream, Tail) :-
|
||
read_line_to_codes(Stream, Tail, NewTail),
|
||
read_header_data(Tail, Stream, NewTail).
|
||
@end example
|
||
|
||
@item read_stream_to_codes(+@var{Stream}, -@var{Codes})
|
||
@findex read_stream_to_codes/3
|
||
@snindex read_stream_to_codes/3
|
||
@cnindex read_stream_to_codes/3
|
||
Read all input until end-of-file and unify the result to @var{Codes}.
|
||
|
||
@item read_stream_to_codes(+@var{Stream}, -@var{Codes}, ?@var{Tail})
|
||
@findex read_stream_to_codes/3
|
||
@snindex read_stream_to_codes/3
|
||
@cnindex read_stream_to_codes/3
|
||
Difference-list version of @code{read_stream_to_codes/2}.
|
||
|
||
@item read_file_to_codes(+@var{Spec}, -@var{Codes}, +@var{Options})
|
||
@findex read_file_to_codes/3
|
||
@snindex read_file_to_codes/3
|
||
@cnindex read_file_to_codes/3
|
||
Read a file to a list of character codes. Currently ignores
|
||
@var{Options}.
|
||
|
||
@c @var{Spec} is a
|
||
@c file-specification for absolute_file_name/3. @var{Codes} is the
|
||
@c resulting code-list. @var{Options} is a list of options for
|
||
@c absolute_file_name/3 and open/4. In addition, the option
|
||
@c \term{tail}{Tail} is defined, forming a difference-list.
|
||
|
||
@item read_file_to_terms(+@var{Spec}, -@var{Terms}, +@var{Options})
|
||
@findex read_file_to_terms/3
|
||
@snindex read_file_to_terms/3
|
||
@cnindex read_file_to_terms/3
|
||
Read a file to a list of prolog terms (see read/1). @c @var{Spec} is a
|
||
@c file-specification for absolute_file_name/3. @var{Terms} is the
|
||
@c resulting list of Prolog terms. @var{Options} is a list of options for
|
||
@c absolute_file_name/3 and open/4. In addition, the option
|
||
@c \term{tail}{Tail} is defined, forming a difference-list.
|
||
@c \end{description}
|
||
|
||
@end table
|
||
|
||
|
||
|
||
@node Red-Black Trees, RegExp, Read Utilities, Library
|
||
@section Red-Black Trees
|
||
@cindex Red-Black Trees
|
||
|
||
Red-Black trees are balanced search binary trees. They are named because
|
||
nodes can be classified as either red or black. The code we include is
|
||
based on "Introduction to Algorithms", second edition, by Cormen,
|
||
Leiserson, Rivest and Stein. The library includes routines to insert,
|
||
lookup and delete elements in the tree.
|
||
|
||
@table @code
|
||
@item rb_new(?@var{T})
|
||
@findex rb_new/1
|
||
@snindex rb_new/1
|
||
@cnindex rb_new/1
|
||
Create a new tree.
|
||
|
||
@item rb_empty(?@var{T})
|
||
@findex rb_empty/1
|
||
@snindex rb_empty/1
|
||
@cnindex rb_empty/1
|
||
Succeeds if tree @var{T} is empty.
|
||
|
||
@item is_rbtree(+@var{T})
|
||
@findex is_rbtree/1
|
||
@snindex is_rbtree/1
|
||
@cnindex is_rbtree/1
|
||
Check whether @var{T} is a valid red-black tree.
|
||
|
||
@item rb_insert(+@var{T0},+@var{Key},?@var{Value},+@var{TF})
|
||
@findex rb_insert/4
|
||
@snindex rb_insert/4
|
||
@cnindex rb_insert/4
|
||
Add an element with key @var{Key} and @var{Value} to the tree
|
||
@var{T0} creating a new red-black tree @var{TF}. Duplicated elements are not
|
||
allowed.
|
||
|
||
@item rb_lookup(+@var{Key},-@var{Value},+@var{T})
|
||
@findex rb_lookup/3
|
||
@snindex rb_lookup/3
|
||
@cnindex rb_lookup/3
|
||
Backtrack through all elements with key @var{Key} in the red-black tree
|
||
@var{T}, returning for each the value @var{Value}.
|
||
|
||
@item rb_lookupall(+@var{Key},-@var{Value},+@var{T})
|
||
@findex rb_lookupall/3
|
||
@snindex rb_lookupall/3
|
||
@cnindex rb_lookupall/3
|
||
Lookup all elements with key @var{Key} in the red-black tree
|
||
@var{T}, returning the value @var{Value}.
|
||
|
||
@item rb_delete(+@var{T},+@var{Key},-@var{TN})
|
||
@findex rb_delete/3
|
||
@snindex rb_delete/3
|
||
@cnindex rb_delete/3
|
||
Delete element with key @var{Key} from the tree @var{T}, returning a new
|
||
tree @var{TN}.
|
||
|
||
@item rb_delete(+@var{T},+@var{Key},-@var{Val},-@var{TN})
|
||
@findex rb_delete/4
|
||
@snindex rb_delete/4
|
||
@cnindex rb_delete/4
|
||
Delete element with key @var{Key} from the tree @var{T}, returning the
|
||
value @var{Val} associated with the key and a new tree @var{TN}.
|
||
|
||
@item rb_del_min(+@var{T},-@var{Key},-@var{Val},-@var{TN})
|
||
@findex rb_del_min/4
|
||
@snindex rb_del_min/4
|
||
@cnindex rb_del_min/4
|
||
Delete the least element from the tree @var{T}, returning the key
|
||
@var{Key}, the value @var{Val} associated with the key and a new tree
|
||
@var{TN}.
|
||
|
||
@item rb_del_max(+@var{T},-@var{Key},-@var{Val},-@var{TN})
|
||
@findex rb_del_max/4
|
||
@snindex rb_del_max/4
|
||
@cnindex rb_del_max/4
|
||
Delete the largest element from the tree @var{T}, returning the key
|
||
@var{Key}, the value @var{Val} associated with the key and a new tree
|
||
@var{TN}.
|
||
|
||
@item rb_update(+@var{T},+@var{Key},+@var{NewVal},-@var{TN})
|
||
@findex rb_update/4
|
||
@snindex rb_update/4
|
||
@cnindex rb_update/4
|
||
Tree @var{TN} is tree @var{T}, but with value for @var{Key} associated
|
||
with @var{NewVal}. Fails if it cannot find @var{Key} in @var{T}.
|
||
|
||
@item rb_apply(+@var{T},+@var{Key},+@var{G},-@var{TN})
|
||
@findex rb_apply/4
|
||
@snindex rb_apply/4
|
||
@cnindex rb_apply/4
|
||
If the value associated with key @var{Key} is @var{Val0} in @var{T}, and
|
||
if @code{call(G,Val0,ValF)} holds, then @var{TN} differs from
|
||
@var{T} only in that @var{Key} is associated with value @var{ValF} in
|
||
tree @var{TN}. Fails if it cannot find @var{Key} in @var{T}, or if
|
||
@code{call(G,Val0,ValF)} is not satisfiable.
|
||
|
||
@item rb_visit(+@var{T},-@var{Pairs})
|
||
@findex rb_visit/2
|
||
@snindex rb_visit/2
|
||
@cnindex rb_visit/2
|
||
@var{Pairs} is an infix visit of tree @var{T}, where each element of
|
||
@var{Pairs} is of the form @var{K}-@var{Val}.
|
||
|
||
@item rb_size(+@var{T},-@var{Size})
|
||
@findex rb_size/2
|
||
@snindex rb_size/2
|
||
@cnindex rb_size/2
|
||
@var{Size} is the number of elements in @var{T}.
|
||
|
||
@item rb_keys(+@var{T},+@var{Keys})
|
||
@findex rb_keys/2
|
||
@snindex rb_keys/2
|
||
@cnindex rb_keys/2
|
||
@var{Keys} is an infix visit with all keys in tree @var{T}. Keys will be
|
||
sorted, but may be duplicate.
|
||
|
||
@item rb_map(+@var{T},+@var{G},-@var{TN})
|
||
@findex rb_map/3
|
||
@snindex rb_map/3
|
||
@cnindex rb_map/3
|
||
For all nodes @var{Key} in the tree @var{T}, if the value associated with
|
||
key @var{Key} is @var{Val0} in tree @var{T}, and if
|
||
@code{call(G,Val0,ValF)} holds, then the value associated with @var{Key}
|
||
in @var{TN} is @var{ValF}. Fails if or if @code{call(G,Val0,ValF)} is not
|
||
satisfiable for all @var{Var0}.
|
||
|
||
@item rb_partial_map(+@var{T},+@var{Keys},+@var{G},-@var{TN})
|
||
@findex rb_partial_map/4
|
||
@snindex rb_partial_map/4
|
||
@cnindex rb_partial_map/4
|
||
For all nodes @var{Key} in @var{Keys}, if the value associated with key
|
||
@var{Key} is @var{Val0} in tree @var{T}, and if @code{call(G,Val0,ValF)}
|
||
holds, then the value associated with @var{Key} in @var{TN} is
|
||
@var{ValF}. Fails if or if @code{call(G,Val0,ValF)} is not satisfiable
|
||
for all @var{Var0}. Assumes keys are not repeated.
|
||
|
||
@item rb_clone(+@var{T},+@var{NT},+@var{Nodes})
|
||
@findex rb_clone/3
|
||
@snindex rb_clone/3
|
||
@cnindex rb_clone/3
|
||
``Clone'' the red-back tree into a new tree with the same keys as the
|
||
original but with all values set to unbound values. Nodes is a list
|
||
containing all new nodes as pairs @var{K-V}.
|
||
|
||
@item rb_min(+@var{T},-@var{Key},-@var{Value})
|
||
@findex rb_min/3
|
||
@snindex rb_min/3
|
||
@cnindex rb_min/3
|
||
@var{Key} is the minimum key in @var{T}, and is associated with @var{Val}.
|
||
|
||
@item rb_max(+@var{T},-@var{Key},-@var{Value})
|
||
@findex rb_max/3
|
||
@snindex rb_max/3
|
||
@cnindex rb_max/3
|
||
@var{Key} is the maximal key in @var{T}, and is associated with @var{Val}.
|
||
|
||
@item rb_next(+@var{T}, +@var{Key},-@var{Next},-@var{Value})
|
||
@findex rb_next/4
|
||
@snindex rb_next/4
|
||
@cnindex rb_next/4
|
||
@var{Next} is the next element after @var{Key} in @var{T}, and is
|
||
associated with @var{Val}.
|
||
|
||
@item rb_previous(+@var{T}, +@var{Key},-@var{Previous},-@var{Value})
|
||
@findex rb_previous/4
|
||
@snindex rb_previous/4
|
||
@cnindex rb_previous/4
|
||
@var{Previous} is the previous element after @var{Key} in @var{T}, and is
|
||
associated with @var{Val}.
|
||
|
||
@item list_to_rbtree(+@var{L}, -@var{T})
|
||
@findex list_to_rbtree/2
|
||
@snindex list_to_rbtree/2
|
||
@cnindex list_to_rbtree/2
|
||
@var{T} is the red-black tree corresponding to the mapping in list @var{L}.
|
||
|
||
@item ord_list_to_rbtree(+@var{L}, -@var{T})
|
||
@findex list_to_rbtree/2
|
||
@snindex list_to_rbtree/2
|
||
@cnindex list_to_rbtree/2
|
||
@var{T} is the red-black tree corresponding to the mapping in ordered
|
||
list @var{L}.
|
||
@end table
|
||
|
||
@node RegExp, Splay Trees, Red-Black Trees, Library
|
||
@section Regular Expressions
|
||
@cindex regular expressions
|
||
|
||
This library includes routines to determine whether a regular expression
|
||
matches part or all of a string. The routines can also return which
|
||
parts parts of the string matched the expression or subexpressions of
|
||
it. This library relies on Henry Spencer's @code{C}-package and is only
|
||
available in operating systems that support dynamic loading. The
|
||
@code{C}-code has been obtained from the sources of FreeBSD-4.0 and is
|
||
protected by copyright from Henry Spencer and from the Regents of the
|
||
University of California (see the file library/regex/COPYRIGHT for
|
||
further details).
|
||
|
||
Much of the description of regular expressions below is copied verbatim
|
||
from Henry Spencer's manual page.
|
||
|
||
A regular expression is zero or more branches, separated by ``|''. It
|
||
matches anything that matches one of the branches.
|
||
|
||
A branch is zero or more pieces, concatenated. It matches a match for
|
||
the first, followed by a match for the second, etc.
|
||
|
||
A piece is an atom possibly followed by ``*'', ``+'', or ``?''. An atom
|
||
followed by ``*'' matches a sequence of 0 or more matches of the atom.
|
||
An atom followed by ``+'' matches a sequence of 1 or more matches of the
|
||
atom. An atom followed by ``?'' matches a match of the atom, or the
|
||
null string.
|
||
|
||
An atom is a regular expression in parentheses (matching a match for the
|
||
regular expression), a range (see below), ``.'' (matching any single
|
||
character), ``^'' (matching the null string at the beginning of the
|
||
input string), ``$'' (matching the null string at the end of the input
|
||
string), a ``\'' followed by a single character (matching that
|
||
character), or a single character with no other significance (matching
|
||
that character).
|
||
|
||
A range is a sequence of characters enclosed in ``[]''. It normally
|
||
matches any single character from the sequence. If the sequence begins
|
||
with ``^'', it matches any single character not from the rest of the
|
||
sequence. If two characters in the sequence are separated by ``-'',
|
||
this is shorthand for the full list of ASCII characters between them
|
||
(e.g. ``[0-9]'' matches any decimal digit). To include a literal ``]''
|
||
in the sequence, make it the first character (following a possible
|
||
``^''). To include a literal ``-'', make it the first or last
|
||
character.
|
||
|
||
@table @code
|
||
|
||
@item regexp(+@var{RegExp},+@var{String},+@var{Opts})
|
||
@findex regexp/3
|
||
@snindex regexp/3
|
||
@cnindex regexp/3
|
||
|
||
Match regular expression @var{RegExp} to input string @var{String}
|
||
according to options @var{Opts}. The options may be:
|
||
@itemize @bullet
|
||
@item @code{nocase}: Causes upper-case characters in @var{String} to
|
||
be treated as lower case during the matching process.
|
||
@end itemize
|
||
|
||
@item regexp(+@var{RegExp},+@var{String},+@var{Opts},@var{SubMatchVars})
|
||
@findex regexp/4
|
||
@snindex regexp/4
|
||
@cnindex regexp/4
|
||
|
||
Match regular expression @var{RegExp} to input string @var{String}
|
||
according to options @var{Opts}. The variable @var{SubMatchVars} should
|
||
be originally a list of unbound variables all will contain a sequence of
|
||
matches, that is, the head of @var{SubMatchVars} will contain the
|
||
characters in @var{String} that matched the leftmost parenthesized
|
||
subexpression within @var{RegExp}, the next head of list will contain
|
||
the characters that matched the next parenthesized subexpression to the
|
||
right in @var{RegExp}, and so on.
|
||
|
||
The options may be:
|
||
@itemize @bullet
|
||
@item @code{nocase}: Causes upper-case characters in @var{String} to
|
||
be treated as lower case during the matching process.
|
||
@item @code{indices}: Changes what is stored in
|
||
@var{SubMatchVars}. Instead of storing the matching characters from
|
||
@var{String}, each variable will contain a term of the form @var{IO-IF}
|
||
giving the indices in @var{String} of the first and last characters in
|
||
the matching range of characters.
|
||
|
||
@end itemize
|
||
|
||
In general there may be more than one way to match a regular expression
|
||
to an input string. For example, consider the command
|
||
@example
|
||
regexp("(a*)b*","aabaaabb", [], [X,Y])
|
||
@end example
|
||
Considering only the rules given so far, @var{X} and @var{Y} could end up
|
||
with the values @code{"aabb"} and @code{"aa"}, @code{"aaab"} and
|
||
@code{"aaa"}, @code{"ab"} and @code{"a"}, or any of several other
|
||
combinations. To resolve this potential ambiguity @code{regexp} chooses among
|
||
alternatives using the rule ``first then longest''. In other words, it
|
||
considers the possible matches in order working from left to right
|
||
across the input string and the pattern, and it attempts to match longer
|
||
pieces of the input string before shorter ones. More specifically, the
|
||
following rules apply in decreasing order of priority:
|
||
|
||
|
||
@enumerate
|
||
@item If a regular expression could match two different parts of an
|
||
input string then it will match the one that begins earliest.
|
||
|
||
@item If a regular expression contains "|" operators then the leftmost matching sub-expression is chosen.
|
||
|
||
@item In *, +, and ? constructs, longer matches are chosen in preference to shorter ones.
|
||
|
||
@item In sequences of expression components the components are considered from left to right.
|
||
@end enumerate
|
||
|
||
In the example from above, @code{"(a*)b*"} matches @code{"aab"}: the
|
||
@code{"(a*)"} portion of the pattern is matched first and it consumes
|
||
the leading @code{"aa"}; then the @code{"b*"} portion of the pattern
|
||
consumes the next @code{"b"}. Or, consider the following example:
|
||
@example
|
||
regexp("(ab|a)(b*)c", "abc", [], [X,Y,Z])
|
||
@end example
|
||
|
||
After this command @var{X} will be @code{"abc"}, @var{Y} will be
|
||
@code{"ab"}, and @var{Z} will be an empty string. Rule 4 specifies that
|
||
@code{"(ab|a)"} gets first shot at the input string and Rule 2 specifies
|
||
that the @code{"ab"} sub-expression is checked before the @code{"a"}
|
||
sub-expression. Thus the @code{"b"} has already been claimed before the
|
||
@code{"(b*)"} component is checked and @code{(b*)} must match an empty string.
|
||
|
||
@end table
|
||
|
||
@node Splay Trees, String I/O, RegExp, Library
|
||
@section Splay Trees
|
||
@cindex splay trees
|
||
|
||
Splay trees are explained in the paper "Self-adjusting Binary Search
|
||
Trees", by D.D. Sleator and R.E. Tarjan, JACM, vol. 32, No.3, July 1985,
|
||
p. 668. They are designed to support fast insertions, deletions and
|
||
removals in binary search trees without the complexity of traditional
|
||
balanced trees. The key idea is to allow the tree to become
|
||
unbalanced. To make up for this, whenever we find a node, we move it up
|
||
to the top. We use code by Vijay Saraswat originally posted to the Prolog
|
||
mailing-list.
|
||
|
||
@table @code
|
||
|
||
@item splay_access(-@var{Return},+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_access/5
|
||
@snindex splay_access/5
|
||
@cnindex splay_access/5
|
||
If item @var{Key} is in tree @var{Tree}, return its @var{Val} and
|
||
unify @var{Return} with @code{true}. Otherwise unify @var{Return} with
|
||
@code{null}. The variable @var{NewTree} unifies with the new tree.
|
||
|
||
@item splay_delete(+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_delete/4
|
||
@snindex splay_delete/4
|
||
@cnindex splay_delete/4
|
||
Delete item @var{Key} from tree @var{Tree}, assuming that it is present
|
||
already. The variable @var{Val} unifies with a value for key @var{Key},
|
||
and the variable @var{NewTree} unifies with the new tree. The predicate
|
||
will fail if @var{Key} is not present.
|
||
|
||
@item splay_init(-@var{NewTree})
|
||
@findex splay_init/3
|
||
@snindex splay_init/3
|
||
@cnindex splay_init/3
|
||
Initialize a new splay tree.
|
||
|
||
@item splay_insert(+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_insert/4
|
||
@snindex splay_insert/4
|
||
@cnindex splay_insert/4
|
||
Insert item @var{Key} in tree @var{Tree}, assuming that it is not
|
||
there already. The variable @var{Val} unifies with a value for key
|
||
@var{Key}, and the variable @var{NewTree} unifies with the new
|
||
tree. In our implementation, @var{Key} is not inserted if it is
|
||
already there: rather it is unified with the item already in the tree.
|
||
|
||
@item splay_join(+@var{LeftTree},+@var{RighTree},-@var{NewTree})
|
||
@findex splay_join/3
|
||
@snindex splay_join/3
|
||
@cnindex splay_join/3
|
||
Combine trees @var{LeftTree} and @var{RighTree} into a single
|
||
tree@var{NewTree} containing all items from both trees. This operation
|
||
assumes that all items in @var{LeftTree} are less than all those in
|
||
@var{RighTree} and destroys both @var{LeftTree} and @var{RighTree}.
|
||
|
||
@item splay_split(+@var{Key},?@var{Val},+@var{Tree},-@var{LeftTree},-@var{RightTree})
|
||
@findex splay_split/5
|
||
@snindex splay_split/5
|
||
@cnindex splay_split/5
|
||
Construct and return two trees @var{LeftTree} and @var{RightTree},
|
||
where @var{LeftTree} contains all items in @var{Tree} less than
|
||
@var{Key}, and @var{RightTree} contains all items in @var{Tree}
|
||
greater than @var{Key}. This operations destroys @var{Tree}.
|
||
|
||
@end table
|
||
|
||
@node String I/O, System, Splay Trees, Library
|
||
@section Reading From and Writing To Strings
|
||
@cindex string I/O
|
||
|
||
From Version 4.3.2 onwards YAP implements SICStus Prolog compatible
|
||
String I/O. The library allows users to read from and write to a memory
|
||
buffer as if it was a file. The memory buffer is built from or converted
|
||
to a string of character codes by the routines in library. Therefore, if
|
||
one wants to read from a string the string must be fully instantiated
|
||
before the library built-in opens the string for reading. These commands
|
||
are available through the @code{use_module(library(charsio))} command.
|
||
|
||
@table @code
|
||
|
||
@item format_to_chars(+@var{Form}, +@var{Args}, -@var{Result})
|
||
@findex format_to_chars/3
|
||
@syindex format_to_chars/3
|
||
@cnindex format_to_chars/3
|
||
|
||
Execute the built-in procedure @code{format/2} with form @var{Form} and
|
||
arguments @var{Args} outputting the result to the string of character
|
||
codes @var{Result}.
|
||
|
||
@item format_to_chars(+@var{Form}, +@var{Args}, -@var{Result0}, -@var{Result})
|
||
@findex format_to_chars/4
|
||
@syindex format_to_chars/4
|
||
@cnindex format_to_chars/4
|
||
|
||
Execute the built-in procedure @code{format/2} with form @var{Form} and
|
||
arguments @var{Args} outputting the result to the difference list of
|
||
character codes @var{Result-Result0}.
|
||
|
||
@item write_to_chars(+@var{Term}, -@var{Result})
|
||
@findex write_to_chars/2
|
||
@syindex write_to_chars/2
|
||
@cnindex write_to_chars/2
|
||
|
||
Execute the built-in procedure @code{write/1} with argument @var{Term}
|
||
outputting the result to the string of character codes @var{Result}.
|
||
|
||
@item write_to_chars(+@var{Term}, -@var{Result0}, -@var{Result})
|
||
@findex write_to_chars/3
|
||
@syindex write_to_chars/3
|
||
@cnindex write_to_chars/3
|
||
|
||
Execute the built-in procedure @code{write/1} with argument @var{Term}
|
||
outputting the result to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item atom_to_chars(+@var{Atom}, -@var{Result})
|
||
@findex atom_to_chars/2
|
||
@syindex atom_to_chars/2
|
||
@cnindex atom_to_chars/2
|
||
|
||
Convert the atom @var{Atom} to the string of character codes
|
||
@var{Result}.
|
||
|
||
@item atom_to_chars(+@var{Atom}, -@var{Result0}, -@var{Result})
|
||
@findex atom_to_chars/3
|
||
@syindex atom_to_chars/3
|
||
@cnindex atom_to_chars/3
|
||
|
||
Convert the atom @var{Atom} to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item number_to_chars(+@var{Number}, -@var{Result})
|
||
@findex number_to_chars/2
|
||
@syindex number_to_chars/2
|
||
@cnindex number_to_chars/2
|
||
|
||
Convert the number @var{Number} to the string of character codes
|
||
@var{Result}.
|
||
|
||
@item number_to_chars(+@var{Number}, -@var{Result0}, -@var{Result})
|
||
@findex number_to_chars/3
|
||
@syindex number_to_chars/3
|
||
@cnindex number_to_chars/3
|
||
|
||
Convert the atom @var{Number} to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item read_from_chars(+@var{Chars}, -@var{Term})
|
||
@findex read_from_chars/2
|
||
@syindex read_from_chars/2
|
||
@cnindex read_from_chars/2
|
||
|
||
Parse the list of character codes @var{Chars} and return the result in
|
||
the term @var{Term}. The character codes to be read must terminate with
|
||
a dot character such that either (i) the dot character is followed by
|
||
blank characters; or (ii) the dot character is the last character in the
|
||
string.
|
||
|
||
@item open_chars_stream(+@var{Chars}, -@var{Stream})
|
||
@findex open_chars_stream/2
|
||
@syindex open_chars_stream/2
|
||
@cnindex open_chars_stream/2
|
||
|
||
Open the list of character codes @var{Chars} as a stream @var{Stream}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, -@var{Chars})
|
||
@findex with_output_to_chars/2
|
||
@syindex with_output_to_chars/2
|
||
@cnindex with_output_to_chars/2
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the list of character codes @var{Chars}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, ?@var{Chars0}, -@var{Chars})
|
||
@findex with_output_to_chars/3
|
||
@syindex with_output_to_chars/3
|
||
@cnindex with_output_to_chars/3
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the difference list of character codes
|
||
@var{Chars-Chars0}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, -@var{Stream}, ?@var{Chars0}, -@var{Chars})
|
||
@findex with_output_to_chars/4
|
||
@syindex with_output_to_chars/4
|
||
@cnindex with_output_to_chars/4
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the difference list of character codes
|
||
@var{Chars-Chars0} and @var{Stream} receives the stream corresponding to
|
||
the memory buffer.
|
||
|
||
@end table
|
||
|
||
The implementation of the character IO operations relies on three YAP
|
||
built-ins:
|
||
@table @code
|
||
|
||
@item charsio:open_mem_read_stream(+@var{String}, -@var{Stream})
|
||
Store a string in a memory buffer and output a stream that reads from this
|
||
memory buffer.
|
||
|
||
@item charsio:open_mem_write_stream(-@var{Stream})
|
||
Create a new memory buffer and output a stream that writes to it.
|
||
|
||
@item charsio:peek_mem_write_stream(-@var{Stream}, L0, L)
|
||
Convert the memory buffer associated with stream @var{Stream} to the
|
||
difference list of character codes @var{L-L0}.
|
||
|
||
@end table
|
||
@noindent
|
||
These built-ins are initialized to belong to the module @code{charsio} in
|
||
@code{init.yap}. Novel procedures for manipulating strings by explicitly
|
||
importing these built-ins.
|
||
|
||
YAP does not currently support opening a @code{charsio} stream in
|
||
@code{append} mode, or seeking in such a stream.
|
||
|
||
@node System, Terms, String I/O, Library
|
||
@section Calling The Operating System from YAP
|
||
@cindex Operating System Utilities
|
||
|
||
Yap now provides a library of system utilities compatible with the
|
||
SICStus Prolog system library. This library extends and to some point
|
||
replaces the functionality of Operating System access routines. The
|
||
library includes Unix/Linux and Win32 @code{C} code. They
|
||
are available through the @code{use_module(library(system))} command.
|
||
|
||
@table @code
|
||
|
||
@item datime(datime(-@var{Year}, -@var{Month}, -@var{DayOfTheMonth},
|
||
-@var{Hour}, -@var{Minute}, -@var{Second})
|
||
@findex datime/1
|
||
@syindex datime/1
|
||
@cnindex datime/1
|
||
The @code{datime/1} procedure returns the current date and time, with
|
||
information on @var{Year}, @var{Month}, @var{DayOfTheMonth},
|
||
@var{Hour}, @var{Minute}, and @var{Second}. The @var{Hour} is returned
|
||
on local time. This function uses the WIN32
|
||
@code{GetLocalTime} function or the Unix @code{localtime} function.
|
||
|
||
@example
|
||
?- datime(X).
|
||
|
||
X = datime(2001,5,28,15,29,46) ?
|
||
@end example
|
||
|
||
@item mktime(datime(+@var{Year}, +@var{Month}, +@var{DayOfTheMonth},
|
||
+@var{Hour}, +@var{Minute}, +@var{Second}), -@var{Seconds})
|
||
@findex mktime/2
|
||
@snindex mktime/2
|
||
@cnindex mktime/2
|
||
The @code{mktime/1} procedure returns the number of @var{Seconds}
|
||
elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time
|
||
(UTC). The user provides information on @var{Year}, @var{Month},
|
||
@var{DayOfTheMonth}, @var{Hour}, @var{Minute}, and @var{Second}. The
|
||
@var{Hour} is given on local time. This function uses the WIN32
|
||
@code{GetLocalTime} function or the Unix @code{mktime} function.
|
||
|
||
@example
|
||
?- mktime(datime(2001,5,28,15,29,46),X).
|
||
|
||
X = 991081786 ? ;
|
||
@end example
|
||
|
||
@item delete_file(+@var{File})
|
||
@findex delete_file/1
|
||
@syindex delete_file/1
|
||
@cnindex delete_file/1
|
||
The @code{delete_file/1} procedure removes file @var{File}. If
|
||
@var{File} is a directory, remove the directory @emph{and all its
|
||
subdirectories}.
|
||
|
||
@example
|
||
?- delete_file(x).
|
||
@end example
|
||
|
||
@item delete_file(+@var{File},+@var{Opts})
|
||
@findex delete_file/2
|
||
@syindex delete_file/2
|
||
@cnindex delete_file/2
|
||
The @code{delete_file/2} procedure removes file @var{File} according to
|
||
options @var{Opts}. These options are @code{directory} if one should
|
||
remove directories, @code{recursive} if one should remove directories
|
||
recursively, and @code{ignore} if errors are not to be reported.
|
||
|
||
This example is equivalent to using the @code{delete_file/1} predicate:
|
||
@example
|
||
?- delete_file(x, [recursive]).
|
||
@end example
|
||
|
||
|
||
@item directory_files(+@var{Dir},+@var{List})
|
||
@findex directory_files/2
|
||
@syindex directory_files/2
|
||
@cnindex directory_files/2
|
||
Given a directory @var{Dir}, @code{directory_files/2} procedures a
|
||
listing of all files and directories in the directory:
|
||
@example
|
||
?- directory_files('.',L), writeq(L).
|
||
['Makefile.~1~','sys.so','Makefile','sys.o',x,..,'.']
|
||
@end example
|
||
The predicates uses the @code{dirent} family of routines in Unix
|
||
environments, and @code{findfirst} in WIN32.
|
||
|
||
@item file_exists(+@var{File})
|
||
@findex file_exists/1
|
||
@syindex file_exists/1
|
||
@cnindex file_exists/1
|
||
The atom @var{File} corresponds to an existing file.
|
||
|
||
@item file_exists(+@var{File},+@var{Permissions})
|
||
@findex file_exists/2
|
||
@syindex file_exists/2
|
||
@cnindex file_exists/2
|
||
The atom @var{File} corresponds to an existing file with permissions
|
||
compatible with @var{Permissions}. YAP currently only accepts for
|
||
permissions to be described as a number. The actual meaning of this
|
||
number is Operating System dependent.
|
||
|
||
@item file_property(+@var{File},?@var{Property})
|
||
@findex file_property/2
|
||
@syindex file_property/2
|
||
@cnindex file_property/2
|
||
The atom @var{File} corresponds to an existing file, and @var{Property}
|
||
will be unified with a property of this file. The properties are of the
|
||
form @code{type(@var{Type})}, which gives whether the file is a regular
|
||
file, a directory, a fifo file, or of unknown type;
|
||
@code{size(@var{Size})}, with gives the size for a file, and
|
||
@code{mod_time(@var{Time})}, which gives the last time a file was
|
||
modified according to some Operating System dependent
|
||
timestamp; @code{mode(@var{mode})}, gives the permission flags for the
|
||
file, and @code{linkto(@var{FileName})}, gives the file pointed to by a
|
||
symbolic link. Properties can be obtained through backtracking:
|
||
|
||
@example
|
||
?- file_property('Makefile',P).
|
||
|
||
P = type(regular) ? ;
|
||
|
||
P = size(2375) ? ;
|
||
|
||
P = mod_time(990826911) ? ;
|
||
|
||
no
|
||
@end example
|
||
|
||
@item make_directory(+@var{Dir})
|
||
@findex make_directory/2
|
||
@syindex make_directory/2
|
||
@cnindex make_directory/2
|
||
Create a directory @var{Dir}. The name of the directory must be an atom.
|
||
|
||
@item rename_file(+@var{OldFile},+@var{NewFile})
|
||
@findex rename_file/2
|
||
@syindex rename_file/2
|
||
@cnindex rename_file/2
|
||
Create file @var{OldFile} to @var{NewFile}. This predicate uses the
|
||
@code{C} built-in function @code{rename}.
|
||
|
||
|
||
@item environ(?@var{EnvVar},+@var{EnvValue})
|
||
@findex environ/2
|
||
@syindex environ/2
|
||
@cnindex environ/2
|
||
Unify environment variable @var{EnvVar} with its value @var{EnvValue},
|
||
if there is one. This predicate is backtrackable in Unix systems, but
|
||
not currently in Win32 configurations.
|
||
|
||
@example
|
||
?- environ('HOME',X).
|
||
|
||
X = 'C:\\cygwin\\home\\administrator' ?
|
||
@end example
|
||
|
||
@item host_id(-@var{Id})
|
||
@findex host_id/1
|
||
@syindex host_id/1
|
||
@cnindex host_id/1
|
||
|
||
Unify @var{Id} with an identifier of the current host. Yap uses the
|
||
@code{hostid} function when available,
|
||
|
||
@item host_name(-@var{Name})
|
||
@findex host_name/1
|
||
@syindex host_name/1
|
||
@cnindex host_name/1
|
||
|
||
Unify @var{Name} with a name for the current host. Yap uses the
|
||
@code{hostname} function in Unix systems when available, and the
|
||
@code{GetComputerName} function in WIN32 systems.
|
||
|
||
@item kill(@var{Id},+@var{SIGNAL})
|
||
@findex kill/2
|
||
@syindex kill/2
|
||
@cnindex kill/2
|
||
|
||
Send signal @var{SIGNAL} to process @var{Id}. In Unix this predicate is
|
||
a direct interface to @code{kill} so one can send signals to groups of
|
||
processes. In WIN32 the predicate is an interface to
|
||
@code{TerminateProcess}, so it kills @var{Id} indepent of @var{SIGNAL}.
|
||
|
||
@item mktemp(@var{Spec},-@var{File})
|
||
@findex mktemp/2
|
||
@syindex mktemp/2
|
||
@cnindex mktemp/2
|
||
|
||
Direct interface to @code{mktemp}: given a @var{Spec}, that is a file
|
||
name with six @var{X} to it, create a file name @var{File}. Use
|
||
@code{tmpnam/1} instead.
|
||
|
||
@item pid(-@var{Id})
|
||
@findex pid/1
|
||
@syindex pid/1
|
||
@cnindex pid/1
|
||
|
||
Unify @var{Id} with the process identifier for the current
|
||
process. An interface to the @t{getpid} function.
|
||
|
||
@item tmpnam(-@var{File})
|
||
@findex tmpnam/1
|
||
@syindex tmpnam/1
|
||
@cnindex tmpnam/1
|
||
|
||
Interface with @var{tmpnam}: create an unique file and unify its name
|
||
with @var{File}.
|
||
|
||
@item
|
||
exec(+@var{Command},[+@var{InputStream},+@var{OutputStream},+@var{ErrorStream}],
|
||
-@var{Status})
|
||
@findex exec/3
|
||
@syindex exec/3
|
||
@cnindex exec/3
|
||
Execute command @var{Command} with its streams connected to
|
||
@var{InputStream}, @var{OutputStream}, and @var{ErrorStream}. The result
|
||
for the command is returned in @var{Status}. The command is executed by
|
||
the default shell @code{bin/sh -c} in Unix.
|
||
|
||
The following example demonstrates the use of @code{exec/3} to send a
|
||
command and process its output:
|
||
|
||
@example
|
||
exec(ls,[std,pipe(S),null],P),repeat, get0(S,C), (C = -1, close(S) ! ; put(C)).
|
||
@end example
|
||
|
||
The streams may be one of standard stream, @code{std}, null stream,
|
||
@code{null}, or @code{pipe(S)}, where @var{S} is a pipe stream. Note
|
||
that it is up to the user to close the pipe.
|
||
|
||
@item working_directory(-@var{CurDir},?@var{NextDir})
|
||
@findex working_directory/2
|
||
@syindex working_directory/2
|
||
@cnindex working_directory/2
|
||
Fetch the current directory at @var{CurDir}. If @var{NextDir} is bound
|
||
to an atom, make its value the current working directory.
|
||
|
||
@item popen(+@var{Command}, +@var{TYPE}, -@var{Stream})
|
||
@findex popen/3
|
||
@syindex popen/3
|
||
@cnindex popen/3
|
||
Interface to the @t{popen} function. It opens a process by creating a
|
||
pipe, forking and invoking @var{Command} on the current shell. Since a
|
||
pipe is by definition unidirectional the @var{Type} argument may be
|
||
@code{read} or @code{write}, not both. The stream should be closed
|
||
using @code{close/1}, there is no need for a special @code{pclose}
|
||
command.
|
||
|
||
The following example demonstrates the use of @code{popen/3} to process
|
||
the output of a command, as @code{exec/3} would do:
|
||
|
||
@example
|
||
?- popen(ls,read,X),repeat, get0(X,C), (C = -1, ! ; put(C)).
|
||
|
||
X = 'C:\\cygwin\\home\\administrator' ?
|
||
@end example
|
||
|
||
|
||
The WIN32 implementation of @code{popen/3} relies on @code{exec/3}.
|
||
|
||
@item shell
|
||
@findex shell/0
|
||
@syindex shell/0
|
||
@cnindex shell/0
|
||
Start a new shell and leave Yap in background until the shell
|
||
completes. Yap uses the shell given by the environment variable
|
||
@code{SHELL}. In WIN32 environment YAP will use @code{COMSPEC} if
|
||
@code{SHELL} is undefined.
|
||
|
||
@item shell(+@var{Command})
|
||
@findex shell/1
|
||
@syindex shell/1
|
||
@cnindex shell/1
|
||
Execute command @var{Command} under a new shell. Yap will be in
|
||
background until the command completes. In Unix environments Yap uses
|
||
the shell given by the environment variable @code{SHELL} with the option
|
||
@code{" -c "}. In WIN32 environment YAP will use @code{COMSPEC} if
|
||
@code{SHELL} is undefined, in this case with the option @code{" /c "}.
|
||
|
||
@item shell(+@var{Command},-@var{Status})
|
||
@findex shell/1
|
||
@syindex shell/1
|
||
@cnindex shell/1
|
||
Execute command @var{Command} under a new shell and unify @var{Status}
|
||
with the exit for the command. Yap will be in background until the
|
||
command completes. In Unix environments Yap uses the shell given by the
|
||
environment variable @code{SHELL} with the option @code{" -c "}. In
|
||
WIN32 environment YAP will use @code{COMSPEC} if @code{SHELL} is
|
||
undefined, in this case with the option @code{" /c "}.
|
||
|
||
@item sleep(+@var{Time})
|
||
@findex sleep/1
|
||
@syindex sleep/1
|
||
@cnindex sleep/1
|
||
Block the current process for @var{Time} seconds. The number of seconds
|
||
must be a positive number, and it may an integer or a float. The Unix
|
||
implementation uses @code{usleep} if the number of seconds is below one,
|
||
and @code{sleep} if it is over a second. The WIN32 implementation uses
|
||
@code{Sleep} for both cases.
|
||
|
||
@item system
|
||
@findex system/0
|
||
@syindex system/0
|
||
@cnindex system/0
|
||
Start a new default shell and leave Yap in background until the shell
|
||
completes. Yap uses @code{/bin/sh} in Unix systems and @code{COMSPEC} in
|
||
WIN32.
|
||
|
||
@item system(+@var{Command},-@var{Res})
|
||
@findex system/2
|
||
@syindex system/2
|
||
@cnindex system/2
|
||
Interface to @code{system}: execute command @var{Command} and unify
|
||
@var{Res} with the result.
|
||
|
||
@item wait(+@var{PID},-@var{Status})
|
||
@findex wait/2
|
||
@syindex wait/2
|
||
@cnindex wait/2
|
||
Wait until process @var{PID} terminates, and return its exits @var{Status}.
|
||
|
||
@end table
|
||
|
||
|
||
@node Terms, Cleanup, System, Library
|
||
@section Utilities On Terms
|
||
@cindex utilities on terms
|
||
|
||
The next routines provide a set of commonly used utilities to manipulate
|
||
terms. Most of these utilities have been implemented in @code{C} for
|
||
efficiency. They are available through the
|
||
@code{use_module(library(terms))} command.
|
||
|
||
@table @code
|
||
|
||
@item acyclic_term(?@var{Term})
|
||
@findex cyclic_term/1
|
||
@syindex cyclic_term/1
|
||
@cnindex cyclic_term/1
|
||
Succeed if the argument @var{Term} is an acyclic term.
|
||
|
||
@item cyclic_term(?@var{Term})
|
||
@findex cyclic_term/1
|
||
@syindex cyclic_term/1
|
||
@cnindex cyclic_term/1
|
||
Succeed if the argument @var{Term} is a cyclic term.
|
||
|
||
@item term_hash(+@var{Term}, ?@var{Hash})
|
||
@findex term_hash/2
|
||
@syindex term_hash/2
|
||
@cnindex term_hash/2
|
||
|
||
If @var{Term} is ground unify @var{Hash} with a positive integer
|
||
calculated from the structure of the term. Otherwise the argument
|
||
@var{Hash} is left unbound. The range of the positive integer is from
|
||
@code{0} to, but not including, @code{33554432}.
|
||
|
||
@item term_hash(+@var{Term}, +@var{Depth}, +@var{Range}, ?@var{Hash})
|
||
@findex term_hash/4
|
||
@syindex term_hash/4
|
||
@cnindex term_hash/4
|
||
|
||
Unify @var{Hash} with a positive integer calculated from the structure
|
||
of the term. The range of the positive integer is from @code{0} to, but
|
||
not including, @var{Range}. If @var{Depth} is @code{-1} the whole term
|
||
is considered. Otherwise, the term is considered only up to depth
|
||
@code{1}, where the constants and the principal functor have depth
|
||
@code{1}, and an argument of a term with depth @var{I} has depth @var{I+1}.
|
||
|
||
@item term_variables(?@var{Term}, -@var{Variables})
|
||
@findex term_variables/2
|
||
@syindex term_variables/2
|
||
@cnindex term_variables/2
|
||
|
||
Unify @var{Variables} with a list of all variables in term @var{Term}.
|
||
|
||
@item variant(?@var{Term1}, ?@var{Term2})
|
||
@findex variant/2
|
||
@syindex variant/2
|
||
@cnindex variant/2
|
||
|
||
Succeed if @var{Term1} and @var{Term2} are variant terms.
|
||
|
||
@item subsumes(?@var{Term1}, ?@var{Term2})
|
||
@findex subsumes/2
|
||
@syindex subsumes/2
|
||
@cnindex subsumes/2
|
||
|
||
Succeed if @var{Term1} subsumes @var{Term2}. Variables in term
|
||
@var{Term1} are bound so that the two terms become equal.
|
||
|
||
|
||
@item subsumes_chk(?@var{Term1}, ?@var{Term2})
|
||
@findex subsumes_chk/2
|
||
@syindex subsumes_chk/2
|
||
@cnindex subsumes_chk/2
|
||
|
||
Succeed if @var{Term1} subsumes @var{Term2} but does not bind any
|
||
variable in @var{Term1}.
|
||
|
||
@item variable_in_term(?@var{Term},?@var{Var})
|
||
@findex variable_in_term/2
|
||
@snindex variable_in_term/2
|
||
@cnindex variable_in_term/2
|
||
Succeed if the second argument @var{Var} is a variable and occurs in
|
||
term @var{Term}.
|
||
|
||
@end table
|
||
|
||
@node Cleanup, Timeout, Terms, Library
|
||
@section Call Cleanup
|
||
@cindex cleanup
|
||
|
||
@t{call_cleanup/1} and @t{call_cleanup/2} allow predicates to register
|
||
code for execution after the call is finished. Predicates can be
|
||
declared to be @t{fragile} to ensure that @t{call_cleanup} is called
|
||
for any Goal which needs it. This library is loaded with the
|
||
@code{use_module(library(cleanup))} command.
|
||
|
||
@table @code
|
||
@item :- fragile @var{P},....,@var{Pn}
|
||
@findex fragile
|
||
@syindex fragile
|
||
@cnindex fragile
|
||
Declares the predicate @var{P}=@t{[module:]name/arity} as a fragile
|
||
predicate, module is optional, default is the current
|
||
typein_module. Whenever such a fragile predicate is used in a query
|
||
it will be called through call_cleanup/1.
|
||
@example
|
||
:- fragile foo/1,bar:baz/2.
|
||
@end example
|
||
|
||
@item call_cleanup(+@var{Goal})
|
||
@findex call_cleanup/1
|
||
@syindex call_cleanup/1
|
||
@cnindex call_cleanup/1
|
||
Execute goal @var{Goal} within a cleanup-context. Called predicates
|
||
might register cleanup Goals which are called right after the end of
|
||
the call to @var{Goal}. Cuts and exceptions inside Goal do not prevent the
|
||
execution of the cleanup calls. @t{call_cleanup} might be nested.
|
||
|
||
@item call_cleanup(+@var{Goal}, +@var{CleanUpGoal})
|
||
@findex call_cleanup/2
|
||
@syindex call_cleanup/2
|
||
@cnindex call_cleanup/2
|
||
This is similar to @t{call_cleanup/1} with an additional
|
||
@var{CleanUpGoal} which gets called after @var{Goal} is finished.
|
||
|
||
@item on_cleanup(+@var{CleanUpGoal})
|
||
@findex on_cleanup/1
|
||
@syindex on_cleanup/1
|
||
@cnindex on_cleanup/1
|
||
Any Predicate might registers a @var{CleanUpGoal}. The
|
||
@var{CleanUpGoal} is put onto the current cleanup context. All such
|
||
CleanUpGoals are executed in reverse order of their registration when
|
||
the surrounding cleanup-context ends. This call will throw an exception
|
||
if a predicate tries to register a @var{CleanUpGoal} outside of any
|
||
cleanup-context.
|
||
|
||
@item cleanup_all
|
||
@findex cleanup_all/0
|
||
@syindex cleanup_all/0
|
||
@cnindex cleanup_all/0
|
||
Calls all pending CleanUpGoals and resets the cleanup-system to an
|
||
initial state. Should only be used as one of the last calls in the
|
||
main program.
|
||
|
||
@end table
|
||
|
||
There are some private predicates which could be used in special
|
||
cases, such as manually setting up cleanup-contexts and registering
|
||
CleanUpGoals for other than the current cleanup-context.
|
||
Read the Source Luke.
|
||
|
||
|
||
@node Timeout, Trees, Cleanup, Library
|
||
@section Calls With Timeout
|
||
@cindex timeout
|
||
|
||
The @t{time_out/3} command relies on the @t{alarm/3} built-in to
|
||
implement a call with a maximum time of execution. The command is
|
||
available with the @code{use_module(library(timeout))} command.
|
||
|
||
@table @code
|
||
|
||
|
||
@item time_out(+@var{Goal}, +@var{Timeout}, -@var{Result})
|
||
@findex time_out/3
|
||
@syindex time_out/3
|
||
@cnindex time_out/3
|
||
Execute goal @var{Goal} with time limited @var{Timeout}, where
|
||
@var{Timeout} is measured in milliseconds. If the goal succeeds, unify
|
||
@var{Result} with success. If the timer expires before the goal
|
||
terminates, unify @var{Result} with @t{timeout}.
|
||
|
||
This command is implemented by activating an alarm at procedure
|
||
entry. If the timer expires before the goal completes, the alarm will
|
||
through an exception @var{timeout}.
|
||
|
||
One should note that @code{time_out/3} is not reentrant, that is, a goal
|
||
called from @code{time_out} should never itself call
|
||
@t{time_out}. Moreover, @code{time_out/3} will deactivate any previous
|
||
alarms set by @code{alarm/3} and vice-versa, hence only one of these
|
||
calls should be used in a program.
|
||
|
||
Last, even though the timer is set in milliseconds, the current
|
||
implementation relies on @t{alarm/3}, and therefore can only offer
|
||
precision on the scale of seconds.
|
||
|
||
@end table
|
||
|
||
@node Trees, UGraphs, Timeout, Library
|
||
@section Updatable Binary Trees
|
||
@cindex updatable tree
|
||
|
||
The following queue manipulation routines are available once
|
||
included with the @code{use_module(library(trees))} command.
|
||
|
||
@table @code
|
||
|
||
@item get_label(+@var{Index}, +@var{Tree}, ?@var{Label})
|
||
@findex get_label/3
|
||
@syindex get_label/3
|
||
@cnindex get_label/3
|
||
Treats the tree as an array of @var{N} elements and returns the
|
||
@var{Index}-th.
|
||
|
||
@item list_to_tree(+@var{List}, -@var{Tree})
|
||
@findex list_to_tree/2
|
||
@syindex list_to_tree/2
|
||
@cnindex list_to_tree/2
|
||
Takes a given @var{List} of @var{N} elements and constructs a binary
|
||
@var{Tree}.
|
||
|
||
@item map_tree(+@var{Pred}, +@var{OldTree}, -@var{NewTree})
|
||
@findex map_tree/3
|
||
@syindex map_tree/3
|
||
@cnindex map_tree/3
|
||
Holds when @var{OldTree} and @var{NewTree} are binary trees of the same shape
|
||
and @code{Pred(Old,New)} is true for corresponding elements of the two trees.
|
||
|
||
@item put_label(+@var{Index}, +@var{OldTree}, +@var{Label}, -@var{NewTree})
|
||
@findex put_label/4
|
||
@syindex put_label/4
|
||
@cnindex put_label/4
|
||
constructs a new tree the same shape as the old which moreover has the
|
||
same elements except that the @var{Index}-th one is @var{Label}.
|
||
|
||
@item tree_size(+@var{Tree}, -@var{Size})
|
||
@findex tree_size/2
|
||
@syindex tree_size/2
|
||
@cnindex tree_size/2
|
||
Calculates the number of elements in the @var{Tree}.
|
||
|
||
@item tree_to_list(+@var{Tree}, -@var{List})
|
||
@findex tree_to_list/2
|
||
@syindex tree_to_list/2
|
||
@cnindex tree_to_list/2
|
||
Is the converse operation to list_to_tree.
|
||
|
||
@end table
|
||
|
||
@node UGraphs, DGraphs, Trees, Library
|
||
@section Unweighted Graphs
|
||
@cindex unweighted graphs
|
||
|
||
The following graph manipulation routines are based in code originally
|
||
written by Richard O'Keefe. The code was then extended to be compatible
|
||
with the SICStus Prolog ugraphs library. The routines assume directed
|
||
graphs, undirected graphs may be implemented by using two edges. Graphs
|
||
are represented in one of two ways:
|
||
|
||
@itemize @bullet
|
||
@item The P-representation of a graph is a list of (from-to) vertex
|
||
pairs, where the pairs can be in any old order. This form is
|
||
convenient for input/output.
|
||
|
||
@item The S-representation of a graph is a list of (vertex-neighbors)
|
||
pairs, where the pairs are in standard order (as produced by keysort)
|
||
and the neighbors of each vertex are also in standard order (as
|
||
produced by sort). This form is convenient for many calculations.
|
||
@end itemize
|
||
|
||
These built-ins are available once included with the
|
||
@code{use_module(library(ugraphs))} command.
|
||
|
||
@table @code
|
||
|
||
@item vertices_edges_to_ugraph(+@var{Vertices}, +@var{Edges}, -@var{Graph})
|
||
@findex vertices_edges_to_ugraph/3
|
||
@syindex vertices_edges_to_ugraph/3
|
||
@cnindex vertices_edges_to_ugraph/3
|
||
Given a graph with a set of vertices @var{Vertices} and a set of edges
|
||
@var{Edges}, @var{Graph} must unify with the corresponding
|
||
s-representation. Note that the vertices without edges will appear in
|
||
@var{Vertices} but not in @var{Edges}. Moreover, it is sufficient for a
|
||
vertice to appear in @var{Edges}.
|
||
@example
|
||
?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5],L).
|
||
|
||
L = [1-[3,5],2-[4],3-[],4-[5],5-[]] ?
|
||
|
||
@end example
|
||
In this case all edges are defined implicitly. The next example shows
|
||
three unconnected edges:
|
||
@example
|
||
?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5],L).
|
||
|
||
L = [1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]] ?
|
||
|
||
@end example
|
||
|
||
@item vertices(+@var{Graph}, -@var{Vertices})
|
||
@findex vertices/2
|
||
@syindex vertices/2
|
||
@cnindex vertices/2
|
||
Unify @var{Vertices} with all vertices appearing in graph
|
||
@var{Graph}. In the next example:
|
||
@example
|
||
?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V).
|
||
|
||
L = [1,2,3,4,5]
|
||
@end example
|
||
|
||
@item edges(+@var{Graph}, -@var{Edges})
|
||
@findex edges/2
|
||
@syindex edges/2
|
||
@cnindex edges/2
|
||
Unify @var{Edges} with all edges appearing in graph
|
||
@var{Graph}. In the next example:
|
||
@example
|
||
?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V).
|
||
|
||
L = [1,2,3,4,5]
|
||
@end example
|
||
|
||
@item add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||
@findex add_vertices/3
|
||
@syindex add_vertices/3
|
||
@cnindex add_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
vertices @var{Vertices} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- add_vertices([1-[3,5],2-[4],3-[],4-[5],
|
||
5-[],6-[],7-[],8-[]],
|
||
[0,2,9,10,11],
|
||
NG).
|
||
|
||
NG = [0-[],1-[3,5],2-[4],3-[],4-[5],5-[],
|
||
6-[],7-[],8-[],9-[],10-[],11-[]]
|
||
@end example
|
||
|
||
@item del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||
@findex del_vertices/3
|
||
@syindex del_vertices/3
|
||
@cnindex del_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||
vertices @var{Vertices} and all the edges that start from or go to a
|
||
vertex in @var{Vertices} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- del_vertices([2,1],[1-[3,5],2-[4],3-[],
|
||
4-[5],5-[],6-[],7-[2,6],8-[]],NL).
|
||
|
||
NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]]
|
||
@end example
|
||
|
||
@item add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex add_edges/3
|
||
@syindex add_edges/3
|
||
@cnindex add_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
edges @var{Edges} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- add_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],
|
||
7-[],8-[]],[1-6,2-3,3-2,5-7,3-2,4-5],NL).
|
||
|
||
NL = [1-[3,5,6],2-[3,4],3-[2],4-[5],5-[7],6-[],7-[],8-[]]
|
||
@end example
|
||
|
||
@item del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex del_edges/3
|
||
@syindex del_edges/3
|
||
@cnindex del_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||
are deleted. In the next example:
|
||
@example
|
||
?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[],
|
||
6-[],7-[],8-[]],
|
||
[1-6,2-3,3-2,5-7,3-2,4-5,1-3],NL).
|
||
|
||
NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]]
|
||
@end example
|
||
|
||
@item transpose(+@var{Graph}, -@var{NewGraph})
|
||
@findex transpose/3
|
||
@syindex transpose/3
|
||
@cnindex transpose/3
|
||
Unify @var{NewGraph} with a new graph obtained from @var{Graph} by
|
||
replacing all edges of the form @var{V1-V2} by edges of the form
|
||
@var{V2-V1}. The cost is @code{O(|V|^2)}. In the next example:
|
||
@example
|
||
?- transpose([1-[3,5],2-[4],3-[],
|
||
4-[5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]]
|
||
@end example
|
||
Notice that an undirected graph is its own transpose.
|
||
|
||
@item neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex neighbors/3
|
||
@syindex neighbors/3
|
||
@cnindex neighbors/3
|
||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||
in @var{Graph}. If the vertice is not in the graph fail. In the next
|
||
example:
|
||
@example
|
||
?- neighbors(4,[1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]],
|
||
NL).
|
||
|
||
NL = [1,2,7,5]
|
||
@end example
|
||
|
||
@item neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex neighbours/3
|
||
@syindex neighbours/3
|
||
@cnindex neighbours/3
|
||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||
in @var{Graph}. In the next example:
|
||
@example
|
||
?- neighbours(4,[1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1,2,7,5]
|
||
@end example
|
||
|
||
@item complement(+@var{Graph}, -@var{NewGraph})
|
||
@findex complement/2
|
||
@syindex complement/2
|
||
@cnindex complement/2
|
||
Unify @var{NewGraph} with the graph complementary to @var{Graph}.
|
||
In the next example:
|
||
@example
|
||
?- complement([1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8],
|
||
4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8],
|
||
7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]]
|
||
@end example
|
||
|
||
@item compose(+@var{LeftGraph}, +@var{RightGraph}, -@var{NewGraph})
|
||
@findex compose/3
|
||
@syindex compose/3
|
||
@cnindex compose/3
|
||
Compose the graphs @var{LeftGraph} and @var{RightGraph} to form @var{NewGraph}.
|
||
In the next example:
|
||
@example
|
||
?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
||
|
||
L = [1-[4],2-[1,2,4],3-[]]
|
||
@end example
|
||
|
||
@item top_sort(+@var{Graph}, -@var{Sort})
|
||
@findex top_sort/2
|
||
@syindex top_sort/2
|
||
@cnindex top_sort/2
|
||
Generate the set of nodes @var{Sort} as a topological sorting of graph
|
||
@var{Graph}, if one is possible.
|
||
In the next example we show how topological sorting works for a linear graph:
|
||
@example
|
||
?- top_sort([_138-[_219],_219-[_139], _139-[]],L).
|
||
|
||
L = [_138,_219,_139]
|
||
@end example
|
||
|
||
@item top_sort(+@var{Graph}, -@var{Sort0}, -@var{Sort})
|
||
@findex top_sort/3
|
||
@syindex top_sort/3
|
||
@cnindex top_sort/3
|
||
Generate the difference list @var{Sort}-@var{Sort0} as a topological
|
||
sorting of graph @var{Graph}, if one is possible.
|
||
|
||
@item transitive_closure(+@var{Graph}, +@var{Closure})
|
||
@findex transitive_closure/2
|
||
@syindex transitive_closure/2
|
||
@cnindex transitive_closure/2
|
||
Generate the graph @var{Closure} as the transitive closure of graph
|
||
@var{Graph}.
|
||
In the next example:
|
||
@example
|
||
?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L).
|
||
|
||
L = [1-[2,3,4,5,6],2-[4,5,6],4-[6]]
|
||
@end example
|
||
|
||
@item reachable(+@var{Node}, +@var{Graph}, -@var{Vertices})
|
||
@findex reachable/3
|
||
@syindex reachable/3
|
||
@cnindex reachable/3
|
||
Unify @var{Vertices} with the set of all vertices in graph
|
||
@var{Graph} that are reachable from @var{Node}. In the next example:
|
||
@example
|
||
?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V).
|
||
|
||
V = [1,3,5]
|
||
@end example
|
||
|
||
@end table
|
||
|
||
@node DGraphs, UnDGraphs, UGraphs, Library
|
||
@section Directed Graphs
|
||
@cindex Efficient Directed Graphs
|
||
|
||
The following graph manipulation routines use the red-black tree library
|
||
to try to avoid linear-time scans of the graph for all graph
|
||
operations. Graphs are represented as a red-black tree, where the key is
|
||
the vertex, and the associated value is a list of vertices reachable
|
||
from that vertex through an edge (ie, a list of edges).
|
||
|
||
@table @code
|
||
|
||
@item dgraph_new(+@var{Graph})
|
||
@findex dgraph_new/1
|
||
@snindex dgraph_new/1
|
||
@cnindex dgraph_new/1
|
||
Create a new directed graph. This operation must be performed before
|
||
trying to use the graph.
|
||
|
||
@item dgraph_vertices(+@var{Graph}, -@var{Vertices})
|
||
@findex dgraph_vertices/2
|
||
@snindex dgraph_vertices/2
|
||
@cnindex dgraph_vertices/2
|
||
Unify @var{Vertices} with all vertices appearing in graph
|
||
@var{Graph}.
|
||
|
||
@item dgraph_edge(+@var{N1}, +@var{N2}, +@var{Graph})
|
||
@findex dgraph_edge/2
|
||
@snindex dgraph_edge/2
|
||
@cnindex dgraph_edge/2
|
||
Edge @var{N1}-@var{N2} is an edge in directed graph @var{Graph}.
|
||
|
||
@item dgraph_edges(+@var{Graph}, -@var{Edges})
|
||
@findex dgraph_edges/2
|
||
@snindex dgraph_edges/2
|
||
@cnindex dgraph_edges/2
|
||
Unify @var{Edges} with all edges appearing in graph
|
||
@var{Graph}.
|
||
|
||
@item dgraph_add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||
@findex dgraph_add_vertices/3
|
||
@snindex dgraph_add_vertices/3
|
||
@cnindex dgraph_add_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
vertices @var{Vertices} to the graph @var{Graph}.
|
||
|
||
@item dgraph_del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||
@findex dgraph_del_vertices/3
|
||
@syindex dgraph_del_vertices/3
|
||
@cnindex dgraph_del_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||
vertices @var{Vertices} and all the edges that start from or go to a
|
||
vertex in @var{Vertices} to the graph @var{Graph}.
|
||
|
||
@item dgraph_add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex dgraph_add_edges/3
|
||
@snindex dgraph_add_edges/3
|
||
@cnindex dgraph_add_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
edges @var{Edges} to the graph @var{Graph}.
|
||
|
||
@item dgraph_del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex dgraph_del_edges/3
|
||
@snindex dgraph_del_edges/3
|
||
@cnindex dgraph_del_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||
are deleted.
|
||
|
||
@item dgraph_neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex dgraph_neighbors/3
|
||
@snindex dgraph_neighbors/3
|
||
@cnindex dgraph_neighbors/3
|
||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||
in @var{Graph}. If the vertice is not in the graph fail.
|
||
|
||
@item dgraph_neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex dgraph_neighbours/3
|
||
@snindex dgraph_neighbours/3
|
||
@cnindex dgraph_neighbours/3
|
||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||
in @var{Graph}.
|
||
|
||
@item dgraph_complement(+@var{Graph}, -@var{NewGraph})
|
||
@findex dgraph_complement/2
|
||
@snindex dgraph_complement/2
|
||
@cnindex dgraph_complement/2
|
||
Unify @var{NewGraph} with the graph complementary to @var{Graph}.
|
||
|
||
@item dgraph_transpose(+@var{Graph}, -@var{Transpose})
|
||
@findex dgraph_transpose/2
|
||
@snindex dgraph_transpose/2
|
||
@cnindex dgraph_transpose/2
|
||
Unify @var{NewGraph} with a new graph obtained from @var{Graph} by
|
||
replacing all edges of the form @var{V1-V2} by edges of the form
|
||
@var{V2-V1}.
|
||
|
||
@item dgraph_close(+@var{Graph1}, +@var{Graph2}, -@var{ComposedGraph})
|
||
@findex dgraph_compose/3
|
||
@snindex dgraph_compose/3
|
||
@cnindex dgraph_compose/3
|
||
Unify @var{ComposedGraph} with a new graph obtained by composing
|
||
@var{Graph1} and @var{Graph2}, ie, @var{ComposedGraph} has an edge
|
||
@var{V1-V2} iff there is a @var{V} such that @var{V1-V} in @var{Graph1}
|
||
and @var{V-V2} in @var{Graph2}.
|
||
|
||
@item dgraph_transitive_closure(+@var{Graph}, -@var{Closure})
|
||
@findex dgraph_transitive_closure/2
|
||
@snindex dgraph_transitive_closure/2
|
||
@cnindex dgraph_transitive_closure/2
|
||
Unify @var{Closure} with the transitive closure of graph @var{Graph}.
|
||
|
||
@item dgraph_symmetric_closure(+@var{Graph}, -@var{Closure})
|
||
@findex dgraph_symmetric_closure/2
|
||
@snindex dgraph_symmetric_closure/2
|
||
@cnindex dgraph_symmetric_closure/2
|
||
Unify @var{Closure} with the symmetric closure of graph @var{Graph},
|
||
that is, if @var{Closure} contains an edge @var{U-V} it must also
|
||
contain the edge @var{V-U}.
|
||
|
||
@item dgraph_top_sort(+@var{Graph}, -@var{Vertices})
|
||
@findex dgraph_top_sort/2
|
||
@snindex dgraph_top_sort/2
|
||
@cnindex dgraph_top_sort/2
|
||
Unify @var{Vertices} with the topological sort of graph @var{Graph}.
|
||
|
||
@item dgraph_to_ugraph(+@var{Graph}, -@var{UGraph})
|
||
@findex dgraph_to_ugraph/2
|
||
@snindex dgraph_to_ugraph/2
|
||
@cnindex dgraph_to_ugraph/2
|
||
Unify @var{UGraph} with the representation used by the @var{ugraphs}
|
||
unweighted graphs library, that is, a list of the form
|
||
@var{V-Neighbors}, where @var{V} is a node and @var{Neighbors} the nodes
|
||
children.
|
||
|
||
@item ugraph_to_dgraph( +@var{UGraph}, -@var{Graph})
|
||
@findex ugraph_to_dgraph/2
|
||
@snindex ugraph_to_dgraph/2
|
||
@cnindex ugraph_to_dgraph/2
|
||
Unify @var{Graph} with the directed graph obtain from @var{UGraph},
|
||
represented in the form used in the @var{ugraphs} unweighted graphs
|
||
library.
|
||
@end table
|
||
|
||
@node UnDGraphs, LAM , DGraphs, Library
|
||
@section Undirected Graphs
|
||
@cindex undrected graphs
|
||
|
||
The following graph manipulation routines use the red-black tree graph
|
||
library to implement undirected graphs. Mostly, this is done by having
|
||
two directed edges per undirected edge.
|
||
|
||
@table @code
|
||
|
||
@item undgraph_new(+@var{Graph})
|
||
@findex undgraph_new/1
|
||
@snindex undgraph_new/1
|
||
@cnindex undgraph_new/1
|
||
Create a new directed graph. This operation must be performed before
|
||
trying to use the graph.
|
||
|
||
@item undgraph_vertices(+@var{Graph}, -@var{Vertices})
|
||
@findex undgraph_vertices/2
|
||
@snindex undgraph_vertices/2
|
||
@cnindex undgraph_vertices/2
|
||
Unify @var{Vertices} with all vertices appearing in graph
|
||
@var{Graph}.
|
||
|
||
@item undgraph_edge(+@var{N1}, +@var{N2}, +@var{Graph})
|
||
@findex undgraph_edge/2
|
||
@snindex undgraph_edge/2
|
||
@cnindex undgraph_edge/2
|
||
Edge @var{N1}-@var{N2} is an edge in undirected graph @var{Graph}.
|
||
|
||
@item undgraph_edges(+@var{Graph}, -@var{Edges})
|
||
@findex undgraph_edges/2
|
||
@snindex undgraph_edges/2
|
||
@cnindex undgraph_edges/2
|
||
Unify @var{Edges} with all edges appearing in graph
|
||
@var{Graph}.
|
||
|
||
@item undgraph_add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||
@findex undgraph_add_vertices/3
|
||
@snindex undgraph_add_vertices/3
|
||
@cnindex undgraph_add_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
vertices @var{Vertices} to the graph @var{Graph}.
|
||
|
||
@item undgraph_del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||
@findex undgraph_del_vertices/3
|
||
@syindex undgraph_del_vertices/3
|
||
@cnindex undgraph_del_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||
vertices @var{Vertices} and all the edges that start from or go to a
|
||
vertex in @var{Vertices} to the graph @var{Graph}.
|
||
|
||
@item undgraph_add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex undgraph_add_edges/3
|
||
@snindex undgraph_add_edges/3
|
||
@cnindex undgraph_add_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
edges @var{Edges} to the graph @var{Graph}.
|
||
|
||
@item undgraph_del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex undgraph_del_edges/3
|
||
@snindex undgraph_del_edges/3
|
||
@cnindex undgraph_del_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||
are deleted.
|
||
|
||
@item undgraph_neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex undgraph_neighbors/3
|
||
@snindex undgraph_neighbors/3
|
||
@cnindex undgraph_neighbors/3
|
||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||
in @var{Graph}. If the vertice is not in the graph fail.
|
||
|
||
@item undgraph_neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex undgraph_neighbours/3
|
||
@snindex undgraph_neighbours/3
|
||
@cnindex undgraph_neighbours/3
|
||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||
in @var{Graph}.
|
||
|
||
@item undgraph_complement(+@var{Graph}, -@var{NewGraph})
|
||
@findex undgraph_complement/2
|
||
@snindex undgraph_complement/2
|
||
@cnindex undgraph_complement/2
|
||
Unify @var{NewGraph} with the graph complementary to @var{Graph}.
|
||
|
||
@item dgraph_to_undgraph( +@var{DGraph}, -@var{UndGraph})
|
||
@findex dgraph_to_undgraph/2
|
||
@snindex dgraph_to_undgraph/2
|
||
@cnindex dgraph_to_undgraph/2
|
||
Unify @var{UndGraph} with teh undirected graph obtained from the
|
||
directed graph @var{DGraph}.
|
||
|
||
@end table
|
||
|
||
@node LAM, , UnDGraphs, Library
|
||
@section LAM
|
||
@cindex lam
|
||
|
||
This library provides a set of utilities for interfacing with LAM MPI.
|
||
The following routines are available once included with the
|
||
@code{use_module(library(lam_mpi))} command. The yap should be
|
||
invoked using the LAM mpiexec or mpirun commands (see LAM manual for
|
||
more details).
|
||
|
||
@table @code
|
||
@item mpi_init
|
||
@findex mpi_init/0
|
||
@snindex mpi_init/0
|
||
@cnindex mpi_init/0
|
||
Sets up the mpi environment. This predicate should be called before any other MPI predicate.
|
||
|
||
@item mpi_finalize
|
||
@findex mpi_finalize/0
|
||
@snindex mpi_finalize/0
|
||
@cnindex mpi_finalize/0
|
||
Terminates the MPI execution environment. Every process must call this predicate before exiting.
|
||
|
||
@item mpi_comm_size(-@var{Size})
|
||
@findex mpi_comm_size/1
|
||
@snindex mpi_comm_size/1
|
||
@cnindex mpi_comm_size/1
|
||
Unifies @var{Size} with the number of processes in the MPI environment.
|
||
|
||
|
||
@item mpi_comm_rank(-@var{Rank})
|
||
@findex mpi_comm_rank/1
|
||
@snindex mpi_comm_rank/1
|
||
@cnindex mpi_comm_rank/1
|
||
Unifies @var{Rank} with the rank of the current process in the MPI environment.
|
||
|
||
@item mpi_version(-@var{Major},-@var{Minor})
|
||
@findex mpi_version/2
|
||
@snindex mpi_version/2
|
||
@cnindex mpi_version/2
|
||
Unifies @var{Major} and @var{Minor} with, respectively, the major and minor version of the MPI.
|
||
|
||
|
||
@item mpi_send(+@var{Data},+@var{Dest},+@var{Tag})
|
||
@findex mpi_send/3
|
||
@snindex mpi_send/3
|
||
@cnindex mpi_send/3
|
||
|
||
Blocking communication predicate. The message in @var{Data}, with tag
|
||
@var{Tag}, is sent immediately to the processor with rank @var{Dest}.
|
||
The predicate succeeds after the message being sent.
|
||
|
||
|
||
|
||
@item mpi_isend(+@var{Data},+@var{Dest},+@var{Tag},-@var{Handle})
|
||
@findex mpi_isend/4
|
||
@snindex mpi_isend/4
|
||
@cnindex mpi_isend/4
|
||
|
||
Non blocking communication predicate. The message in @var{Data}, with
|
||
tag @var{Tag}, is sent whenever possible to the processor with rank
|
||
@var{Dest}. An @var{Handle} to the message is returned to be used to
|
||
check for the status of the message, using the @code{mpi_wait} or
|
||
@code{mpi_test} predicates. Until @code{mpi_wait} is called, the
|
||
memory allocated for the buffer containing the message is not
|
||
released.
|
||
|
||
@item mpi_recv(?@var{Source},?@var{Tag},-@var{Data})
|
||
@findex mpi_recv/3
|
||
@snindex mpi_recv/3
|
||
@cnindex mpi_recv/3
|
||
|
||
Blocking communication predicate. The predicate blocks until a message
|
||
is received from processor with rank @var{Source} and tag @var{Tag}.
|
||
The message is placed in @var{Data}.
|
||
|
||
@item mpi_irecv(?@var{Source},?@var{Tag},-@var{Handle})
|
||
@findex mpi_irecv/3
|
||
@snindex mpi_irecv/3
|
||
@cnindex mpi_irecv/3
|
||
|
||
Non-blocking communication predicate. The predicate returns an
|
||
@var{Handle} for a message that will be received from processor with
|
||
rank @var{Source} and tag @var{Tag}. Note that the predicate succeeds
|
||
immediately, even if no message has been received. The predicate
|
||
@code{mpi_wait_recv} should be used to obtain the data associated to
|
||
the handle.
|
||
|
||
@item mpi_wait_recv(?@var{Handle},-@var{Status},-@var{Data})
|
||
@findex mpi_wait_recv/3
|
||
@snindex mpi_wait_recv/3
|
||
@cnindex mpi_wait_recv/3
|
||
|
||
Completes a non-blocking receive operation. The predicate blocks until
|
||
a message associated with handle @var{Hanlde} is buffered. The
|
||
predicate succeeds unifying @var{Status} with the status of the
|
||
message and @var{Data} with the message itself.
|
||
|
||
@item mpi_test_recv(?@var{Handle},-@var{Status},-@var{Data})
|
||
@findex mpi_test_recv/3
|
||
@snindex mpi_test_recv/3
|
||
@cnindex mpi_test_recv/3
|
||
|
||
Provides information regarding a handle. If the message associated
|
||
with handle @var{Hanlde} is buffered then the predicate succeeds
|
||
unifying @var{Status} with the status of the message and @var{Data}
|
||
with the message itself. Otherwise, the predicate fails.
|
||
|
||
|
||
@item mpi_wait(?@var{Handle},-@var{Status})
|
||
@findex mpi_wait/2
|
||
@snindex mpi_wait/2
|
||
@cnindex mpi_wait/2
|
||
|
||
Completes a non-blocking operation. If the operation was a
|
||
@code{mpi_send}, the predicate blocks until the message is buffered
|
||
or sent by the runtime system. At this point the send buffer is
|
||
released. If the operation was a @code{mpi_recv}, it waits until the
|
||
message is copied to the receive buffer. @var{Status} is unified with
|
||
the status of the message.
|
||
|
||
@item mpi_test(?@var{Handle},-@var{Status})
|
||
@findex mpi_test/2
|
||
@snindex mpi_test/2
|
||
@cnindex mpi_test/2
|
||
|
||
Provides information regarding the handle @var{Handle}, ie., if a
|
||
communication operation has been completed. If the operation
|
||
associate with @var{Hanlde} has been completed the predicate succeeds
|
||
with the completion status in @var{Status}, otherwise it fails.
|
||
|
||
@item mpi_barrier
|
||
@findex mpi_barrier/0
|
||
@snindex mpi_barrier/0
|
||
@cnindex mpi_barrier/0
|
||
|
||
Collective communication predicate. Performs a barrier
|
||
synchronization among all processes. Note that a collective
|
||
communication means that all processes call the same predicate. To be
|
||
able to use a regular @code{mpi_recv} to receive the messages, one
|
||
should use @code{mpi_bcast2}.
|
||
|
||
|
||
@item mpi_bcast2(+@var{Root}, +@var{Data})
|
||
@findex mpi_bcast/2
|
||
@snindex mpi_bcast/2
|
||
@cnindex mpi_bcast/2
|
||
|
||
Broadcasts the message @var{Data} from the process with rank @var{Root}
|
||
to all other processes.
|
||
|
||
@item mpi_bcast3(+@var{Root}, +@var{Data}, +@var{Tag})
|
||
@findex mpi_bcast/3
|
||
@snindex mpi_bcast/3
|
||
@cnindex mpi_bcast/3
|
||
|
||
Broadcasts the message @var{Data} with tag @var{Tag} from the process with rank @var{Root}
|
||
to all other processes.
|
||
|
||
@item mpi_ibcast(+@var{Root}, +@var{Data}, +@var{Tag})
|
||
@findex mpi_bcast/3
|
||
@snindex mpi_bcast/3
|
||
@cnindex mpi_bcast/3
|
||
|
||
Non-blocking operation. Broadcasts the message @var{Data} with tag @var{Tag}
|
||
from the process with rank @var{Root} to all other processes.
|
||
|
||
@item mpi_gc
|
||
@findex mpi_gc/0
|
||
@snindex mpi_gc/0
|
||
@cnindex mpi_gc/0
|
||
|
||
Attempts to perform garbage collection with all the open handles
|
||
associated with send and non-blocking broadcasts. For each handle it
|
||
tests it and the message has been delivered the handle and the buffer
|
||
are released.
|
||
|
||
@end table
|
||
|
||
|
||
@node SWI-Prolog, Extensions, Library, Top
|
||
@cindex SWI-Prolog
|
||
|
||
@menu SWI-Prolog Emulation
|
||
Subnodes of SWI-Prolog
|
||
* Invoking Predicates on all Members of a List :: maplist and friends
|
||
* Forall :: forall built-in
|
||
* hProlog and SWI-Prolog Attributed Variables :: Emulating SWI-like attributed variables
|
||
* SWI-Prolog Global Variables :: Emulating SWI-like attributed variables
|
||
@end menu
|
||
|
||
@include swi.tex
|
||
|
||
@menu
|
||
Extensions to Traditional Prolog
|
||
|
||
* Rational Trees:: Working with Rational Trees
|
||
* Coroutining:: Changing the Execution of Goals
|
||
* Attributed Variables:: Using attributed Variables
|
||
* CLPR:: The CLP(R) System
|
||
* Logtalk:: The Logtalk Object-Oriented system
|
||
* Threads:: Thread Library
|
||
* Parallelism:: Running in Or-Parallel
|
||
* Tabling:: Storing Intermediate Solutions of programs
|
||
* Low Level Profiling:: Profiling Abstract Machine Instructions
|
||
* Low Level Tracing:: Tracing at Abstract Machine Level
|
||
@end menu
|
||
|
||
@node Rational Trees, Coroutining, , Extensions
|
||
@section Rational Trees
|
||
|
||
Prolog unification is not a complete implementation. For efficiency
|
||
considerations, Prolog systems do not perform occur checks while
|
||
unifying terms. As an example, @code{X = a(X)} will not fail but instead
|
||
will create an infinite term of the form @code{a(a(a(a(a(...)))))}, or
|
||
@emph{rational tree}.
|
||
|
||
Rational trees are no supported by default in YAP. In previous
|
||
versions, this was not the default and these terms could easily lead
|
||
to infinite computation. For example, @code{X = a(X), X = X} would
|
||
enter an infinite loop.
|
||
|
||
The @code{RATIONAL_TREES} flag improves support for these
|
||
terms. Internal primitives are now aware that these terms can exist, and
|
||
will not enter infinite loops. Hence, the previous unification will
|
||
succeed. Another example, @code{X = a(X), ground(X)} will succeed
|
||
instead of looping. Other affected built-ins include the term comparison
|
||
primitives, @code{numbervars/3}, @code{copy_term/2}, and the internal
|
||
data base routines. The support does not extend to Input/Output routines
|
||
or to @code{assert/1} YAP does not allow directly reading
|
||
rational trees, and you need to use @code{write_depth/2} to avoid
|
||
entering an infinite cycle when trying to write an infinite term.
|
||
|
||
@node Coroutining, Attributed Variables, Rational Trees, Extensions
|
||
@section Coroutining
|
||
|
||
Prolog uses a simple left-to-right flow of control. It is sometimes
|
||
convenient to change this control so that goals will only be executed
|
||
when conditions are fulfilled. This may result in a more "data-driven"
|
||
execution, or may be necessary to correctly implement extensions such as
|
||
negation by default.
|
||
|
||
The @code{COROUTINING} flag enables this option. Note that the support for
|
||
coroutining will in general slow down execution.
|
||
|
||
The following declaration is supported:
|
||
|
||
@table @code
|
||
@item block/1
|
||
The argument to @code{block/1} is a condition on a goal or a conjunction
|
||
of conditions, with each element separated by commas. Each condition is
|
||
of the form @code{predname(@var{C1},...,@var{CN})}, where @var{N} is the
|
||
arity of the goal, and each @var{CI} is of the form @code{-}, if the
|
||
argument must suspend until the variable is bound, or @code{?}, otherwise.
|
||
|
||
@item wait/1
|
||
The argument to @code{wait/1} is a predicate descriptor or a conjunction
|
||
of these predicates. These predicates will suspend until their first
|
||
argument is bound.
|
||
@end table
|
||
|
||
The following primitives are supported:
|
||
|
||
@table @code
|
||
@item dif(@var{X},@var{Y})
|
||
@findex dif/2
|
||
@syindex dif/2
|
||
@cnindex dif/2
|
||
Succeed if the two arguments do not unify. A call to @code{dif/2} will
|
||
suspend if unification may still succeed or fail, and will fail if they
|
||
always unify.
|
||
|
||
@item freeze(?@var{X},:@var{G})
|
||
@findex freeze/2
|
||
@syindex freeze/2
|
||
@cnindex freeze/2
|
||
Delay execution of goal @var{G} until the variable @var{X} is bound.
|
||
|
||
@item frozen(@var{X},@var{G})
|
||
@findex frozen/2
|
||
@syindex frozen/2
|
||
@cnindex frozen/2
|
||
Unify @var{G} with a conjunction of goals suspended on variable @var{X},
|
||
or @code{true} if no goal has suspended.
|
||
|
||
@item when(+@var{C},:@var{G})
|
||
@findex when/2
|
||
@syindex when/2
|
||
@cnindex when/2
|
||
Delay execution of goal @var{G} until the conditions @var{C} are
|
||
satisfied. The conditions are of the following form:
|
||
|
||
@table @code
|
||
@item @var{C1},@var{C2}
|
||
Delay until both conditions @var{C1} and @var{C2} are satisfied.
|
||
@item @var{C1};@var{C2}
|
||
Delay until either condition @var{C1} or condition @var{C2} is satisfied.
|
||
@item ?=(@var{V1},@var{C2})
|
||
Delay until terms @var{V1} and @var{V1} have been unified.
|
||
@item nonvar(@var{V})
|
||
Delay until variable @var{V} is bound.
|
||
@item ground(@var{V})
|
||
Delay until variable @var{V} is ground.
|
||
@end table
|
||
|
||
Note that @code{when/2} will fail if the conditions fail.
|
||
|
||
@item call_residue(:@var{G},@var{L})
|
||
@findex call_residue/2
|
||
@syindex call_residue/2
|
||
@cnindex call_residue/2
|
||
|
||
Call goal @var{G}. If subgoals of @var{G} are still blocked, return
|
||
a list containing these goals and the variables they are blocked in. The
|
||
goals are then considered as unblocked. The next example shows a case
|
||
where @code{dif/2} suspends twice, once outside @code{call_residue/2},
|
||
and the other inside:
|
||
|
||
@example
|
||
?- dif(X,Y),
|
||
call_residue((dif(X,Y),(X = f(Z) ; Y = f(Z))), L).
|
||
|
||
X = f(Z),
|
||
L = [[Y]-dif(f(Z),Y)],
|
||
dif(f(Z),Y) ? ;
|
||
|
||
Y = f(Z),
|
||
L = [[X]-dif(X,f(Z))],
|
||
dif(X,f(Z)) ? ;
|
||
|
||
no
|
||
@end example
|
||
The system only reports one invocation of @code{dif/2} as having
|
||
suspended.
|
||
|
||
@end table
|
||
|
||
@node Attributed Variables, CLPR, Coroutining, Extensions
|
||
@chapter Attributed Variables
|
||
@cindex attributed variables
|
||
|
||
@menu
|
||
|
||
* Attribute Declarations:: Declaring New Attributes
|
||
* Attribute Manipulation:: Setting and Reading Attributes
|
||
* Attributed Unification:: Tuning the Unification Algorithm
|
||
* Displaying Attributes:: Displaying Attributes in User-Readable Form
|
||
* Projecting Attributes:: Obtaining the Attributes of Interest
|
||
* Attribute Examples:: Two Simple Examples of how to use Attributes.
|
||
@end menu
|
||
|
||
YAP now supports the attributed variables packaged developed at OFAI by
|
||
Christian Holzbaur. Attributes are a means of declaring that an
|
||
arbitrary term is a property for a variable. These properties can be
|
||
updated during forward execution. Moreover, the unification algorithm is
|
||
aware of attributed variables and will call user defined handlers when
|
||
trying to unify these variables.
|
||
|
||
Attributed variables provide an elegant abstraction over which one can
|
||
extend Prolog systems. Their main application so far has been in
|
||
implementing constraint handlers, such as Holzbaur's CLPQR and Fruewirth
|
||
and Holzbaur's CHR, but other applications have been proposed in the
|
||
literature.
|
||
|
||
|
||
The command
|
||
@example
|
||
| ?- use_module(library(atts)).
|
||
@end example
|
||
enables the use of attributed variables. The package provides the
|
||
following functionality:
|
||
@itemize @bullet
|
||
@item Each attribute must be declared first. Attributes are described by a functor
|
||
and are declared per module. Each Prolog module declares its own sets of
|
||
attributes. Different modules may have different functors with the same
|
||
module.
|
||
@item The built-in @code{put_atts/2} adds or deletes attributes to a
|
||
variable. The variable may be unbound or may be an attributed
|
||
variable. In the latter case, YAP discards previous values for the
|
||
attributes.
|
||
@item The built-in @code{get_atts/2} can be used to check the values of
|
||
an attribute associated with a variable.
|
||
@item The unification algorithm calls the user-defined predicate
|
||
@t{verify_attributes/3} before trying to bind an attributed
|
||
variable. Unification will resume after this call.
|
||
@item The user-defined predicate
|
||
@t{attribute_goal/2} converts from an attribute to a goal.
|
||
@item The user-defined predicate
|
||
@t{project_attributes/2} is used from a set of variables into a set of
|
||
constraints or goals. One application of @t{project_attributes/2} is in
|
||
the top-level, where it is used to output the set of
|
||
floundered constraints at the end of a query.
|
||
@end itemize
|
||
|
||
@node Attribute Declarations, Attribute Manipulation, , Attributed Variables
|
||
@section Attribute Declarations
|
||
|
||
Attributes are compound terms associated with a variable. Each attribute
|
||
has a @emph{name} which is @emph{private} to the module in which the
|
||
attribute was defined. Variables may have at most one attribute with a
|
||
name. Attribute names are defined with the following declaration:
|
||
|
||
@cindex attribute declaration
|
||
@cindex declaration, attribute
|
||
@findex attribute/1 (declaration)
|
||
|
||
@example
|
||
:- attribute @var{AttributeSpec}, ..., @var{AttributeSpec}.
|
||
@end example
|
||
|
||
@noindent
|
||
where each @var{AttributeSpec} has the form (@var{Name}/@var{Arity}).
|
||
One single such declaration is allowed per module @var{Module}.
|
||
|
||
Although the YAP module system is predicate based, attributes are local
|
||
to modules. This is implemented by rewriting all calls to the
|
||
built-ins that manipulate attributes so that attribute names are
|
||
preprocessed depending on the module. The @code{user:goal_expansion/3}
|
||
mechanism is used for this purpose.
|
||
|
||
|
||
@node Attribute Manipulation, Attributed Unification, Attribute Declarations, Attributed Variables
|
||
@section Attribute Manipulation
|
||
|
||
|
||
The attribute manipulation predicates always work as follows:
|
||
@enumerate
|
||
@item The first argument is the unbound variable associated with
|
||
attributes,
|
||
@item The second argument is a list of attributes. Each attribute will
|
||
be a Prolog term or a constant, prefixed with the @t{+} and @t{-} unary
|
||
operators. The prefix @t{+} may be dropped for convenience.
|
||
@end enumerate
|
||
|
||
The following three procedures are available to the user. Notice that
|
||
these built-ins are rewritten by the system into internal built-ins, and
|
||
that the rewriting process @emph{depends} on the module on which the
|
||
built-ins have been invoked.
|
||
|
||
@table @code
|
||
@item @var{Module}:get_atts(@var{-Var},@var{?ListOfAttributes})
|
||
@findex get_atts/2
|
||
@syindex get_atts/2
|
||
@cnindex get_atts/2
|
||
Unify the list @var{?ListOfAttributes} with the attributes for the unbound
|
||
variable @var{Var}. Each member of the list must be a bound term of the
|
||
form @code{+(@var{Attribute})}, @code{-(@var{Attribute})} (the @t{kbd}
|
||
prefix may be dropped). The meaning of @t{+} and @t{-} is:
|
||
@item +(@var{Attribute})
|
||
Unifies @var{Attribute} with a corresponding attribute associated with
|
||
@var{Var}, fails otherwise.
|
||
|
||
@item -(@var{Attribute})
|
||
Succeeds if a corresponding attribute is not associated with
|
||
@var{Var}. The arguments of @var{Attribute} are ignored.
|
||
|
||
@item @var{Module}:put_atts(@var{-Var},@var{?ListOfAttributes})
|
||
@findex put_atts/2
|
||
@syindex put_atts/2
|
||
@cnindex put_atts/2
|
||
Associate with or remove attributes from a variable @var{Var}. The
|
||
attributes are given in @var{?ListOfAttributes}, and the action depends
|
||
on how they are prefixed:
|
||
@item +(@var{Attribute})
|
||
Associate @var{Var} with @var{Attribute}. A previous value for the
|
||
attribute is simply replace (like with @code{set_mutable/2}).
|
||
|
||
@item -(@var{Attribute})
|
||
Remove the attribute with the same name. If no such attribute existed,
|
||
simply succeed.
|
||
@end table
|
||
|
||
@node Attributed Unification, Displaying Attributes, Attribute Manipulation, Attributed Variables
|
||
@section Attributed Unification
|
||
|
||
The user-predicate predicate @code{verify_attributes/3} is called when
|
||
attempting to unify an attributed variable which might have attributes
|
||
in some @var{Module}.
|
||
|
||
@table @code
|
||
@item @var{Module}:verify_attributes(@var{-Var}, @var{+Value}, @var{-Goals})
|
||
@findex verify_attributes/3
|
||
@syindex verify_attributes/3
|
||
@cnindex verify_attributes/3
|
||
|
||
The predicate is called when trying to unify the attributed variable
|
||
@var{Var} with the Prolog term @var{Value}. Note that @var{Value} may be
|
||
itself an attributed variable, or may contain attributed variables. The
|
||
goal @t{verify_attributes/3} is actually called before @var{Var} is
|
||
unified with @var{Value}.
|
||
|
||
It is up to the user to define which actions may be performed by
|
||
@t{verify_attributes/3} but the procedure is expected to return in
|
||
@var{Goals} a list of goals to be called @emph{after} @var{Var} is
|
||
unified with @var{Value}. If @t{verify_attributes/3} fails, the
|
||
unification will fail.
|
||
|
||
Notice that the @t{verify_attributes/3} may be called even if @var{Var}
|
||
has no attributes in module @t{Module}. In this case the routine should
|
||
simply succeed with @var{Goals} unified with the empty list.
|
||
|
||
@item attvar(@var{-Var})
|
||
@findex attvar/1
|
||
@snindex attvar/1
|
||
@cnindex attvar/1
|
||
Succeed if @var{Var} is an attributed variable.
|
||
@end table
|
||
|
||
|
||
|
||
@node Displaying Attributes, Projecting Attributes,Attributed Unification, Attributed Variables
|
||
@section Displaying Attributes
|
||
|
||
Attributes are usually presented as goals. The following routines are
|
||
used by built-in predicates such as @code{call_residue/2} and by the
|
||
Prolog top-level to display attributes:
|
||
|
||
@table @code
|
||
@item @var{Module}:attribute_goal(@var{-Var}, @var{-Goal})
|
||
@findex attribute_goal/2
|
||
@syindex attribute_goal/2
|
||
@cnindex attribute_goal/2
|
||
User-defined procedure, called to convert the attributes in @var{Var} to
|
||
a @var{Goal}. Should fail when no interpretation is available.
|
||
|
||
@item @var{Module}:project_attributes(@var{-QueryVars}, @var{+AttrVars})
|
||
@findex project_attributes/2
|
||
@syindex project_attributes/2
|
||
@cnindex project_attributes/2
|
||
User-defined procedure, called to project the attributes in the query,
|
||
@var{AttrVars}, given that the set of variables in the query is
|
||
@var{QueryVars}.
|
||
|
||
@end table
|
||
|
||
@node Projecting Attributes, Attribute Examples, Displaying Attributes, Attributed Variables
|
||
@section Projecting Attributes
|
||
|
||
Constraint solvers must be able to project a set of constraints to a set
|
||
of variables. This is useful when displaying the solution to a goal, but
|
||
may also be used to manipulate computations. The user-defined
|
||
@code{project_attributes/2} is responsible for implementing this
|
||
projection.
|
||
|
||
|
||
@table @code
|
||
@item @var{Module}:project_attributes(@var{+QueryVars}, @var{+AttrVars})
|
||
@findex project_attributes/2
|
||
@syindex project_attributes/2
|
||
@cnindex project_attributes/2
|
||
Given a list of variables @var{QueryVars} and list of attributed
|
||
variables @var{AttrVars}, project all attributes in @var{AttrVars} to
|
||
@var{QueryVars}. Although projection is constraint system dependent,
|
||
typically this will involve expressing all constraints in terms of
|
||
@var{QueryVars} and considering all remaining variables as existentially
|
||
quantified.
|
||
@end table
|
||
|
||
Projection interacts with @code{attribute_goal/2} at the prolog top
|
||
level. When the query succeeds, the system first calls
|
||
@code{project_attributes/2}. The system then calls
|
||
@code{attribute_goal/2} to get a user-level representation of the
|
||
constraints. Typically, @code{attribute_goal/2} will convert from the
|
||
original constraints into a set of new constraints on the projection,
|
||
and these constraints are the ones that will have an
|
||
@code{attribute_goal/2} handler.
|
||
|
||
@node Attribute Examples, ,Projecting Attributes, Attributed Variables
|
||
@section Attribute Examples
|
||
|
||
The following two examples example is taken from the SICStus Prolog manual. It
|
||
sketches the implementation of a simple finite domain ``solver''. Note
|
||
that an industrial strength solver would have to provide a wider range
|
||
of functionality and that it quite likely would utilize a more efficient
|
||
representation for the domains proper. The module exports a single
|
||
predicate @code{domain(@var{-Var},@var{?Domain})} which associates
|
||
@var{Domain} (a list of terms) with @var{Var}. A variable can be
|
||
queried for its domain by leaving @var{Domain} unbound.
|
||
|
||
We do not present here a definition for @code{project_attributes/2}.
|
||
Projecting finite domain constraints happens to be difficult.
|
||
|
||
|
||
@example
|
||
:- module(domain, [domain/2]).
|
||
|
||
:- use_module(library(atts)).
|
||
:- use_module(library(ordsets), [
|
||
ord_intersection/3,
|
||
ord_intersect/2,
|
||
list_to_ord_set/2
|
||
]).
|
||
|
||
:- attribute dom/1.
|
||
|
||
verify_attributes(Var, Other, Goals) :-
|
||
get_atts(Var, dom(Da)), !, % are we involved?
|
||
( var(Other) -> % must be attributed then
|
||
( get_atts(Other, dom(Db)) -> % has a domain?
|
||
ord_intersection(Da, Db, Dc),
|
||
Dc = [El|Els], % at least one element
|
||
( Els = [] -> % exactly one element
|
||
Goals = [Other=El] % implied binding
|
||
; Goals = [],
|
||
put_atts(Other, dom(Dc))% rescue intersection
|
||
)
|
||
; Goals = [],
|
||
put_atts(Other, dom(Da)) % rescue the domain
|
||
)
|
||
; Goals = [],
|
||
ord_intersect([Other], Da) % value in domain?
|
||
).
|
||
verify_attributes(_, _, []). % unification triggered
|
||
% because of attributes
|
||
% in other modules
|
||
|
||
attribute_goal(Var, domain(Var,Dom)) :- % interpretation as goal
|
||
get_atts(Var, dom(Dom)).
|
||
|
||
domain(X, Dom) :-
|
||
var(Dom), !,
|
||
get_atts(X, dom(Dom)).
|
||
domain(X, List) :-
|
||
list_to_ord_set(List, Set),
|
||
Set = [El|Els], % at least one element
|
||
( Els = [] -> % exactly one element
|
||
X = El % implied binding
|
||
; put_atts(Fresh, dom(Set)),
|
||
X = Fresh % may call
|
||
% verify_attributes/3
|
||
).
|
||
@end example
|
||
|
||
Note that the ``implied binding'' @code{Other=El} was deferred until after
|
||
the completion of @code{verify_attribute/3}. Otherwise, there might be a
|
||
danger of recursively invoking @code{verify_attribute/3}, which might bind
|
||
@code{Var}, which is not allowed inside the scope of @code{verify_attribute/3}.
|
||
Deferring unifications into the third argument of @code{verify_attribute/3}
|
||
effectively serializes the calls to @code{verify_attribute/3}.
|
||
|
||
Assuming that the code resides in the file @file{domain.yap}, we
|
||
can use it via:
|
||
|
||
@example
|
||
| ?- use_module(domain).
|
||
@end example
|
||
|
||
Let's test it:
|
||
|
||
@example
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]).
|
||
|
||
domain(X,[1,5,6,7]),
|
||
domain(Y,[3,4,5,6]),
|
||
domain(Z,[1,6,7,8]) ?
|
||
|
||
yes
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]),
|
||
X=Y.
|
||
|
||
Y = X,
|
||
domain(X,[5,6]),
|
||
domain(Z,[1,6,7,8]) ?
|
||
|
||
yes
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]),
|
||
X=Y, Y=Z.
|
||
|
||
X = 6,
|
||
Y = 6,
|
||
Z = 6
|
||
@end example
|
||
|
||
To demonstrate the use of the @var{Goals} argument of
|
||
@code{verify_attributes/3}, we give an implementation of
|
||
@code{freeze/2}. We have to name it @code{myfreeze/2} in order to
|
||
avoid a name clash with the built-in predicate of the same name.
|
||
|
||
@example
|
||
:- module(myfreeze, [myfreeze/2]).
|
||
|
||
:- use_module(library(atts)).
|
||
|
||
:- attribute frozen/1.
|
||
|
||
verify_attributes(Var, Other, Goals) :-
|
||
get_atts(Var, frozen(Fa)), !, % are we involved?
|
||
( var(Other) -> % must be attributed then
|
||
( get_atts(Other, frozen(Fb)) % has a pending goal?
|
||
-> put_atts(Other, frozen((Fa,Fb))) % rescue conjunction
|
||
; put_atts(Other, frozen(Fa)) % rescue the pending goal
|
||
),
|
||
Goals = []
|
||
; Goals = [Fa]
|
||
).
|
||
verify_attributes(_, _, []).
|
||
|
||
attribute_goal(Var, Goal) :- % interpretation as goal
|
||
get_atts(Var, frozen(Goal)).
|
||
|
||
myfreeze(X, Goal) :-
|
||
put_atts(Fresh, frozen(Goal)),
|
||
Fresh = X.
|
||
@end example
|
||
|
||
Assuming that this code lives in file @file{myfreeze.yap},
|
||
we would use it via:
|
||
|
||
@example
|
||
| ?- use_module(myfreeze).
|
||
| ?- myfreeze(X,print(bound(x,X))), X=2.
|
||
|
||
bound(x,2) % side effect
|
||
X = 2 % bindings
|
||
@end example
|
||
|
||
The two solvers even work together:
|
||
|
||
@example
|
||
| ?- myfreeze(X,print(bound(x,X))), domain(X,[1,2,3]),
|
||
domain(Y,[2,10]), X=Y.
|
||
|
||
bound(x,2) % side effect
|
||
X = 2, % bindings
|
||
Y = 2
|
||
@end example
|
||
|
||
The two example solvers interact via bindings to shared attributed
|
||
variables only. More complicated interactions are likely to be found
|
||
in more sophisticated solvers. The corresponding
|
||
@code{verify_attributes/3} predicates would typically refer to the
|
||
attributes from other known solvers/modules via the module prefix in
|
||
@code{@var{Module}:get_atts/2}.
|
||
|
||
@node CLPR, CHR, Attributed Variables, Extensions
|
||
@cindex CLPQ
|
||
@cindex CLPR
|
||
|
||
@menu
|
||
* CLPR Solver Predicates::
|
||
* CLPR Syntax::
|
||
* CLPR Unification::
|
||
* CLPR Non-linear Constraints::
|
||
@end menu
|
||
|
||
@include clpr.tex
|
||
|
||
@node CHR, Logtalk, CLPR, Top
|
||
|
||
@menu
|
||
* CHR Introduction::
|
||
* CHR Syntax and Semantics::
|
||
* CHR in YAP Programs::
|
||
* CHR Debugging::
|
||
* CHR Examples::
|
||
* CHR Compatibility::
|
||
* CHR Guidelines::
|
||
@end menu
|
||
|
||
@include chr.tex
|
||
|
||
@node Logtalk, Threads, CHR, Extensions
|
||
@chapter Logtalk
|
||
@cindex Logtalk
|
||
|
||
|
||
The Logtalk object-oriented extension is available once included
|
||
with the @code{use_module(library(logtalk))} command. Note that,
|
||
although we load Logtalk using the @code{use_module/1} built-in
|
||
predicate, the system is not packaged as a module not does it use
|
||
modules in its implementation.
|
||
|
||
Logtalk documentation is included in the Logtalk directory. Be sure to read the Logtalk/INSTALL file for additional instructions on how to customize your Logtalk installation to match your working environment (the @code{use_module/1} call described above only provides minimal support).
|
||
|
||
For the latest Logtalk news, please see the URL @url{http://www.logtalk.org/}.
|
||
|
||
@node Threads, Parallelism, Logtalk, Extensions
|
||
@chapter Threads
|
||
|
||
YAP implements a SWI-Prolog compatible multithreading
|
||
library. Like in SWI-Prolog, Prolog threads have their own stacks and
|
||
only share the Prolog @emph{heap}: predicates, records, flags and other
|
||
global non-backtrackable data. The package is based on the POSIX thread
|
||
standard (Butenhof:1997:PPT) used on most popular systems except
|
||
for MS-Windows.
|
||
|
||
@comment On Windows it uses the
|
||
@comment \url[pthread-win32]{http://sources.redhat.com/pthreads-win32/} emulation
|
||
@comment of POSIX threads mixed with the Windows native API for smoother and
|
||
@comment faster operation.
|
||
|
||
@menu
|
||
Subnodes of Threads
|
||
* Creating and Destroying Prolog Threads::
|
||
* Monitoring Threads::
|
||
* Thread Communication::
|
||
* Thread Synchronisation::
|
||
|
||
Subnodes of Thread Communication
|
||
* Message Queues::
|
||
* Signalling Threads::
|
||
* Threads and Dynamic Predicates::
|
||
@end menu
|
||
|
||
@node Creating and Destroying Prolog Threads, Monitoring Threads, ,Threads
|
||
@section Creating and Destroying Prolog Threads
|
||
|
||
@table @code
|
||
|
||
@item thread_create(:@var{Goal}, -@var{Id}, +@var{Options})
|
||
@findex thread_create/3
|
||
@snindex thread_create/3
|
||
@cnindex thread_create/3
|
||
|
||
Create a new Prolog thread (and underlying C-thread) and start it
|
||
by executing @var{Goal}. If the thread is created succesfully, the
|
||
thread-identifier of the created thread is unified to @var{Id}.
|
||
@var{Options} is a list of options. Currently defined options are:
|
||
|
||
@table @code
|
||
@item stack
|
||
Set the limit in K-Bytes to which the Prolog stacks of
|
||
this thread may grow. If omited, the limit of the calling thread is
|
||
used. See also the commandline @code{-S} option.
|
||
|
||
@item trail
|
||
Set the limit in K-Bytes to which the trail stack of this thread may
|
||
grow. If omited, the limit of the calling thread is used. See also the
|
||
commandline option @code{-T}.
|
||
|
||
@item alias
|
||
Associate an alias-name with the thread. This named may be used to
|
||
refer to the thread and remains valid until the thread is joined
|
||
(see @code{thread_join/2}).
|
||
|
||
@item detached
|
||
If @code{false} (default), the thread can be waited for using
|
||
@code{thread_join/2}. @code{thread_join/2} must be called on this thread
|
||
to reclaim the all resources associated to the thread. If @code{true},
|
||
the system will reclaim all associated resources automatically after the
|
||
thread finishes. Please note that thread identifiers are freed for reuse
|
||
after a detached thread finishes or a normal thread has been joined.
|
||
See also @code{thread_join/2} and @code{thread_detach/1}.
|
||
@end table
|
||
|
||
The @var{Goal} argument is @emph{copied} to the new Prolog engine.
|
||
This implies further instantiation of this term in either thread does
|
||
not have consequences for the other thread: Prolog threads do not share
|
||
data from their stacks.
|
||
|
||
@item thread_self(-@var{Id})
|
||
@findex thread_self/1
|
||
@snindex thread_self/1
|
||
@cnindex thread_self/1
|
||
Get the Prolog thread identifier of the running thread. If the thread
|
||
has an alias, the alias-name is returned.
|
||
|
||
@item thread_join(+@var{Id}, -@var{Status})
|
||
@findex thread_join/2
|
||
@snindex thread_join/2
|
||
@cnindex thread_join/2
|
||
Wait for the termination of thread with given @var{Id}. Then unify the
|
||
result-status of the thread with @var{Status}. After this call,
|
||
@var{Id} becomes invalid and all resources associated with the thread
|
||
are reclaimed. Note that threads with the attribute @code{detached}
|
||
@code{true} cannot be joined. See also @code{current_thread/2}.
|
||
|
||
A thread that has been completed without @code{thread_join/2} being
|
||
called on it is partly reclaimed: the Prolog stacks are released and the
|
||
C-thread is destroyed. A small data-structure representing the
|
||
exit-status of the thread is retained until @code{thread_join/2} is called on
|
||
the thread. Defined values for @var{Status} are:
|
||
|
||
@table @code
|
||
@item true
|
||
The goal has been proven successfully.
|
||
|
||
@item false
|
||
The goal has failed.
|
||
|
||
@item exception(@var{Term})
|
||
The thread is terminated on an
|
||
exception. See @code{print_message/2} to turn system exceptions into
|
||
readable messages.
|
||
|
||
@item exited(@var{Term})
|
||
The thread is terminated on @code{thread_exit/1} using the argument @var{Term}.
|
||
@end table
|
||
|
||
|
||
@item thread_detach(+@var{Id})
|
||
@findex thread_detach/1
|
||
@snindex thread_detach/1
|
||
@cnindex thread_detach/1
|
||
Switch thread into detached-state (see @code{detached} option at
|
||
@code{thread_create/3} at runtime. @var{Id} is the identifier of the thread
|
||
placed in detached state.
|
||
|
||
One of the possible applications is to simplify debugging. Threads that
|
||
are created as @code{detached} leave no traces if they crash. For
|
||
not-detached threads the status can be inspected using
|
||
@code{current_thread/2}. Threads nobody is waiting for may be created
|
||
normally and detach themselves just before completion. This way they
|
||
leave no traces on normal completion and their reason for failure can be
|
||
inspected.
|
||
|
||
@item thread_yield
|
||
@findex thread_yield/0
|
||
@snindex thread_yield/0
|
||
@cnindex thread_yield/0
|
||
Voluntarily relinquish the processor.
|
||
|
||
@item thread_exit(+@var{Term})
|
||
@findex thread_exit/1
|
||
@snindex thread_exit/1
|
||
@cnindex thread_exit/1
|
||
Terminates the thread immediately, leaving @code{exited(@var{Term})} as
|
||
result-state for @code{thread_join/2}. If the thread has the attribute
|
||
@code{detached} @code{true} it terminates, but its exit status cannot be
|
||
retrieved using @code{thread_join/2} making the value of @var{Term}
|
||
irrelevant. The Prolog stacks and C-thread are reclaimed.
|
||
|
||
@item thread_at_exit(:@var{Term})
|
||
@findex thread_at_exit/1
|
||
@snindex thread_at_exit/1
|
||
@cnindex thread_at_exit/1
|
||
Run @var{Goal} just before releasing the thread resources. This is to
|
||
be compared to @code{at_halt/1}, but only for the current
|
||
thread. These hooks are ran regardless of why the execution of the
|
||
thread has been completed. As these hooks are run, the return-code is
|
||
already available through @code{current_thread/2} using the result of
|
||
@code{thread_self/1} as thread-identifier.
|
||
|
||
@item thread_setconcurrency(+@var{Old}, -@var{New})
|
||
@findex thread_setconcurrency/2
|
||
@snindex thread_setconcurrency/2
|
||
@cnindex thread_setconcurrency/2
|
||
Determine the concurrency of the process, which is defined as the
|
||
maximum number of concurrently active threads. `Active' here means
|
||
they are using CPU time. This option is provided if the
|
||
thread-implementation provides
|
||
@code{pthread_setconcurrency()}. Solaris is a typical example of this
|
||
family. On other systems this predicate unifies @var{Old} to 0 (zero)
|
||
and succeeds silently.
|
||
|
||
@item thread_sleep(+@var{Time})
|
||
@findex thread_sleep/1
|
||
@snindex thread_sleep/1
|
||
@cnindex thread_sleep/1
|
||
Make current thread sleep for @var{Time} seconds. @var{Time} may be an
|
||
integer or a floating point number. This call should not be used if
|
||
alarms are also being used.
|
||
@end table
|
||
|
||
|
||
@node Monitoring Threads, Thread Communication,Creating and Destroying Prolog Threads,Threads
|
||
@section Monitoring Threads
|
||
|
||
Normal multi-threaded applications should not need these the predicates
|
||
from this section because almost any usage of these predicates is
|
||
unsafe. For example checking the existence of a thread before signalling
|
||
it is of no use as it may vanish between the two calls. Catching
|
||
exceptions using @code{catch/3} is the only safe way to deal with
|
||
thread-existence errors.
|
||
|
||
These predicates are provided for diagnosis and monitoring tasks.
|
||
|
||
|
||
@table @code
|
||
@item current_thread(+@var{Id}, -@var{Status})
|
||
@findex current_thread/2
|
||
@snindex current_thread/2
|
||
@cnindex current_thread/2
|
||
Enumerates identifiers and status of all currently known threads.
|
||
Calling current_thread/2 does not influence any thread. See also
|
||
@code{thread_join/2}. For threads that have an alias-name, this name is
|
||
returned in @var{Id} instead of the numerical thread identifier.
|
||
@var{Status} is one of:
|
||
|
||
@table @code
|
||
@item running
|
||
The thread is running. This is the initial status of a thread. Please
|
||
note that threads waiting for something are considered running too.
|
||
|
||
@item false
|
||
The @var{Goal} of the thread has been completed and failed.
|
||
|
||
@item true
|
||
The @var{Goal} of the thread has been completed and succeeded.
|
||
|
||
@item exited(@var{Term})
|
||
The @var{Goal} of the thread has been terminated using @code{thread_exit/1}
|
||
with @var{Term} as argument. If the underlying native thread has
|
||
exited (using pthread_exit()) @var{Term} is unbound.
|
||
|
||
@item exception(@var{Term})
|
||
The @var{Goal} of the thread has been terminated due to an uncaught
|
||
exception (see @code{throw/1} and @code{catch/3}).
|
||
@end table
|
||
|
||
@item thread_statistics(+@var{Id}, +@var{Key}, -@var{Value})
|
||
@findex thread_statistics/3
|
||
@snindex thread_statistics/3
|
||
@cnindex thread_statistics/3
|
||
Obtains statistical information on thread @var{Id} as @code{statistics/2}
|
||
does in single-threaded applications. This call returns all keys
|
||
of @code{statistics/2}, although only information statistics about the
|
||
stacks and CPU time yield different values for each thread.
|
||
|
||
@item mutex_statistics
|
||
@findex mutex_statistics/0
|
||
@snindex mutex_statistics/0
|
||
@cnindex mutex_statistics/0
|
||
Print usage statistics on internal mutexes and mutexes associated
|
||
with dynamic predicates. For each mutex two numbers are printed:
|
||
the number of times the mutex was acquired and the number of
|
||
collisions: the number times the calling thread has to
|
||
wait for the mutex. The collistion-count is not available on
|
||
Windows as this would break portability to Windows-95/98/ME or
|
||
significantly harm performance. Generally collision count is
|
||
close to zero on single-CPU hardware.
|
||
|
||
@item threads
|
||
@findex threads/0
|
||
@snindex threads/0
|
||
@cnindex threads/0
|
||
Prints a table of current threads and their status.
|
||
@end table
|
||
|
||
|
||
@node Thread Communication, Thread Synchronisation, Monitoring Threads, Threads
|
||
@section Thread communication
|
||
|
||
@menu
|
||
Subnodes of Thread Communication
|
||
* Message Queues::
|
||
* Signalling Threads::
|
||
* Threads and Dynamic Predicates::
|
||
@end menu
|
||
|
||
@node Message Queues, Signalling Threads, ,Thread Communication
|
||
@subsection Message Queues
|
||
|
||
Prolog threads can exchange data using dynamic predicates, database
|
||
records, and other globally shared data. These provide no suitable means
|
||
to wait for data or a condition as they can only be checked in an
|
||
expensive polling loop. @emph{Message queues} provide a means for
|
||
threads to wait for data or conditions without using the CPU.
|
||
|
||
Each thread has a message-queue attached to it that is identified
|
||
by the thread. Additional queues are created using
|
||
@code{message_queue_create/2}.
|
||
|
||
@table @code
|
||
@item thread_send_message(+@var{QueueOrThreadId}, +@var{Term})
|
||
@findex thread_send_message/2
|
||
@snindex thread_send_message/2
|
||
@cnindex thread_send_message/2
|
||
Place @var{Term} in the given queue or default queue of the indicated
|
||
thread (which can even be the message queue of itself (see
|
||
@code{thread_self/1}). Any term can be placed in a message queue, but note that
|
||
the term is copied to the receiving thread and variable-bindings are
|
||
thus lost. This call returns immediately.
|
||
|
||
If more than one thread is waiting for messages on the given queue and
|
||
at least one of these is waiting with a partially instantiated
|
||
@var{Term}, the waiting threads are @emph{all} sent a wakeup signal,
|
||
starting a rush for the available messages in the queue. This behaviour
|
||
can seriously harm performance with many threads waiting on the same
|
||
queue as all-but-the-winner perform a useless scan of the queue. If
|
||
there is only one waiting thread or all waiting threads wait with an
|
||
unbound variable an arbitrary thread is restarted to scan the queue.%
|
||
@comment \footnote{See the documentation for the POSIX thread functions
|
||
@comment pthread_cond_signal() v.s.\ pthread_cond_broadcastt()
|
||
@comment for background information.}
|
||
|
||
@item thread_get_message(?@var{Term})
|
||
@findex thread_get_message/1
|
||
@snindex thread_get_message/1
|
||
@cnindex thread_get_message/1
|
||
Examines the thread message-queue and if necessary blocks execution
|
||
until a term that unifies to @var{Term} arrives in the queue. After
|
||
a term from the queue has been unified unified to @var{Term}, the
|
||
term is deleted from the queue and this predicate returns.
|
||
|
||
Please note that not-unifying messages remain in the queue. After
|
||
the following has been executed, thread 1 has the term @code{gnu}
|
||
in its queue and continues execution using @var{A} is @code{gnat}.
|
||
|
||
@example
|
||
<thread 1>
|
||
thread_get_message(a(A)),
|
||
|
||
<thread 2>
|
||
thread_send_message(b(gnu)),
|
||
thread_send_message(a(gnat)),
|
||
@end example
|
||
|
||
See also @code{thread_peek_message/1}.
|
||
|
||
@item thread_peek_message(?@var{Term})
|
||
@findex thread_peek_message/1
|
||
@snindex thread_peek_message/1
|
||
@cnindex thread_peek_message/1
|
||
Examines the thread message-queue and compares the queued terms
|
||
with @var{Term} until one unifies or the end of the queue has been
|
||
reached. In the first case the call succeeds (possibly instantiating
|
||
@var{Term}. If no term from the queue unifies this call fails.
|
||
|
||
@item thread_message_queue_create(?@var{Queue})
|
||
@findex thread_message_queue_create/1
|
||
@snindex thread_message_queue_create/1
|
||
@cnindex thread_message_queue_create/1
|
||
If @var{Queue} is an atom, create a named queue. To avoid ambiguity
|
||
on @code{thread_send_message/2}, the name of a queue may not be in use
|
||
as a thread-name. If @var{Queue} is unbound an anonymous queue is
|
||
created and @var{Queue} is unified to its identifier.
|
||
|
||
@item thread_message_queue_destroy(+@var{Queue})
|
||
@findex thread_message_queue_destroy/1
|
||
@snindex thread_message_queue_destroy/1
|
||
@cnindex thread_message_queue_destroy/1
|
||
Destroy a message queue created with message_queue_create/1. It is
|
||
@emph{not} allows to destroy the queue of a thread. Neither is it
|
||
allowed to destroy a queue other threads are waiting for or, for
|
||
anynymous message queues, may try to wait for later.%
|
||
|
||
@item thread_get_message(+@var{Queue}, +@var{Term})
|
||
@findex thread_get_message/2
|
||
@snindex thread_get_message/2
|
||
@cnindex thread_get_message/2
|
||
As thread_get_message/1, operating on a given queue. It is allowed to
|
||
peek into another thread's message queue, an operation that can be used
|
||
to check whether a thread has swallowed a message sent to it.
|
||
@end table
|
||
|
||
|
||
Explicit message queues are designed with the @emph{worker-pool} model
|
||
in mind, where multiple threads wait on a single queue and pick up the
|
||
first goal to execute. Below is a simple implementation where the
|
||
workers execute arbitrary Prolog goals. Note that this example provides
|
||
no means to tell when all work is done. This must be realised using
|
||
additional synchronisation.
|
||
|
||
@example
|
||
% create_workers(+Id, +N)
|
||
%
|
||
% Create a pool with given Id and number of workers.
|
||
|
||
create_workers(Id, N) :-
|
||
message_queue_create(Id),
|
||
forall(between(1, N, _),
|
||
thread_create(do_work(Id), _, [])).
|
||
|
||
do_work(Id) :-
|
||
repeat,
|
||
thread_get_message(Id, Goal),
|
||
( catch(Goal, E, print_message(error, E))
|
||
-> true
|
||
; print_message(error, goal_failed(Goal, worker(Id)))
|
||
),
|
||
fail.
|
||
|
||
% work(+Id, +Goal)
|
||
%
|
||
% Post work to be done by the pool
|
||
|
||
work(Id, Goal) :-
|
||
thread_send_message(Id, Goal).
|
||
@end example
|
||
|
||
@node Signalling Threads, Threads and Dynamic Predicates,Message Queues, Thread Communication
|
||
@subsection Signalling Threads
|
||
|
||
These predicates provide a mechanism to make another thread execute some
|
||
goal as an @emph{interrupt}. Signalling threads is safe as these
|
||
interrupts are only checked at safe points in the virtual machine.
|
||
Nevertheless, signalling in multi-threaded environments should be
|
||
handled with care as the receiving thread may hold a @emph{mutex}
|
||
(see with_mutex). Signalling probably only makes sense to start
|
||
debugging threads and to cancel no-longer-needed threads with @code{throw/1},
|
||
where the receiving thread should be designed carefully do handle
|
||
exceptions at any point.
|
||
|
||
@table @code
|
||
@item thread_signal(+@var{ThreadId}, :@var{Goal})
|
||
@findex thread_signal/2
|
||
@snindex thread_signal/2
|
||
@cnindex thread_signal/2
|
||
Make thread @var{ThreadId} execute @var{Goal} at the first
|
||
opportunity. In the current implementation, this implies at the first
|
||
pass through the @emph{Call-port}. The predicate @code{thread_signal/2}
|
||
itself places @var{Goal} into the signalled-thread's signal queue
|
||
and returns immediately.
|
||
|
||
Signals (interrupts) do not cooperate well with the world of
|
||
multi-threading, mainly because the status of mutexes cannot be
|
||
guaranteed easily. At the call-port, the Prolog virtual machine
|
||
holds no locks and therefore the asynchronous execution is safe.
|
||
|
||
@var{Goal} can be any valid Prolog goal, including @code{throw/1} to make
|
||
the receiving thread generate an exception and @code{trace/0} to start
|
||
tracing the receiving thread.
|
||
|
||
@comment In the Windows version, the receiving thread immediately executes
|
||
@comment the signal if it reaches a Windows GetMessage() call, which generally
|
||
@comment happens of the thread is waiting for (user-)input.
|
||
@end table
|
||
|
||
@node Threads and Dynamic Predicates, , Signalling Threads, Thread Communication
|
||
@subsection Threads and Dynamic Predicates
|
||
|
||
Besides queues threads can share and exchange data using dynamic
|
||
predicates. The multi-threaded version knows about two types of
|
||
dynamic predicates. By default, a predicate declared @emph{dynamic}
|
||
(see @code{dynamic/1}) is shared by all threads. Each thread may
|
||
assert, retract and run the dynamic predicate. Synchronisation inside
|
||
Prolog guarantees the consistency of the predicate. Updates are
|
||
@emph{logical}: visible clauses are not affected by assert/retract
|
||
after a query started on the predicate. In many cases primitive from
|
||
thread synchronysation should be used to ensure application invariants on
|
||
the predicate are maintained.
|
||
|
||
Besides shared predicates, dynamic predicates can be declared with the
|
||
@code{thread_local/1} directive. Such predicates share their
|
||
attributes, but the clause-list is different in each thread.
|
||
|
||
@table @code
|
||
@item thread_local(@var{+Functor/Arity})
|
||
@findex thread_local/1 (directive)
|
||
@snindex thread_local/1 (directive)
|
||
@cnindex thread_local/1 (directive)
|
||
related to the dynamic/1 directive. It tells the system that the
|
||
predicate may be modified using @code{assert/1}, @code{retract/1},
|
||
etc, during execution of the program. Unlike normal shared dynamic
|
||
data however each thread has its own clause-list for the predicate.
|
||
As a thread starts, this clause list is empty. If there are still
|
||
clauses as the thread terminates these are automatically reclaimed by
|
||
the system. The thread_local property implies
|
||
the property dynamic.
|
||
|
||
Thread-local dynamic predicates are intended for maintaining
|
||
thread-specific state or intermediate results of a computation.
|
||
|
||
It is not recommended to put clauses for a thread-local predicate into
|
||
a file as in the example below as the clause is only visible from the
|
||
thread that loaded the source-file. All other threads start with an
|
||
empty clause-list.
|
||
|
||
@example
|
||
:- thread_local
|
||
foo/1.
|
||
|
||
foo(gnat).
|
||
@end example
|
||
|
||
@end table
|
||
|
||
|
||
@node Thread Synchronisation, , Thread Communication, Threads
|
||
@section Thread Synchronisation
|
||
|
||
All internal Prolog operations are thread-safe. This implies two Prolog
|
||
threads can operate on the same dynamic predicate without corrupting the
|
||
consistency of the predicate. This section deals with user-level
|
||
@emph{mutexes} (called @emph{monitors} in ADA or
|
||
@emph{critical-sections} by Microsoft). A mutex is a
|
||
@emph{MUT}ual @emph{EX}clusive device, which implies at most one thread
|
||
can @emph{hold} a mutex.
|
||
|
||
Mutexes are used to realise related updates to the Prolog database.
|
||
With `related', we refer to the situation where a `transaction' implies
|
||
two or more changes to the Prolog database. For example, we have a
|
||
predicate @code{address/2}, representing the address of a person and we want
|
||
to change the address by retracting the old and asserting the new
|
||
address. Between these two operations the database is invalid: this
|
||
person has either no address or two addresses, depending on the
|
||
assert/retract order.
|
||
|
||
Here is how to realise a correct update:
|
||
|
||
@example
|
||
:- initialization
|
||
mutex_create(addressbook).
|
||
|
||
change_address(Id, Address) :-
|
||
mutex_lock(addressbook),
|
||
retractall(address(Id, _)),
|
||
asserta(address(Id, Address)),
|
||
mutex_unlock(addressbook).
|
||
@end example
|
||
|
||
|
||
@table @code
|
||
@item mutex_create(?@var{MutexId})
|
||
@findex mutex_create/1
|
||
@snindex mutex_create/1
|
||
@cnindex mutex_create/1
|
||
Create a mutex. if @var{MutexId} is an atom, a @emph{named} mutex is
|
||
created. If it is a variable, an anonymous mutex reference is returned.
|
||
There is no limit to the number of mutexes that can be created.
|
||
|
||
@item mutex_destroy(+@var{MutexId})
|
||
@findex mutex_destroy/1
|
||
@snindex mutex_destroy/1
|
||
@cnindex mutex_destroy/1
|
||
Destroy a mutex. After this call, @var{MutexId} becomes invalid and
|
||
further references yield an @code{existence_error} exception.
|
||
|
||
@item with_mutex(+@var{MutexId}, :@var{Goal})
|
||
@findex with_mutex/2
|
||
@snindex with_mutex/2
|
||
@cnindex with_mutex/2
|
||
Execute @var{Goal} while holding @var{MutexId}. If @var{Goal} leaves
|
||
choicepoints, these are destroyed (as in @code{once/1}). The mutex is unlocked
|
||
regardless of whether @var{Goal} succeeds, fails or raises an exception.
|
||
An exception thrown by @var{Goal} is re-thrown after the mutex has been
|
||
successfully unlocked. See also @code{mutex_create/2}.
|
||
|
||
Although described in the thread-section, this predicate is also
|
||
available in the single-threaded version, where it behaves simply as
|
||
once/1.
|
||
|
||
@item mutex_lock(+@var{MutexId})
|
||
@findex mutex_lock/1
|
||
@snindex mutex_lock/1
|
||
@cnindex mutex_lock/1
|
||
Lock the mutex. Prolog mutexes are @emph{recursive} mutexes: they
|
||
can be locked multiple times by the same thread. Only after unlocking
|
||
it as many times as it is locked, the mutex becomes available for
|
||
locking by other threads. If another thread has locked the mutex the
|
||
calling thread is suspended until to mutex is unlocked.
|
||
|
||
If @var{MutexId} is an atom, and there is no current mutex with that
|
||
name, the mutex is created automatically using @code{mutex_create/1}. This
|
||
implies named mutexes need not be declared explicitly.
|
||
|
||
Please note that locking and unlocking mutexes should be paired
|
||
carefully. Especially make sure to unlock mutexes even if the protected
|
||
code fails or raises an exception. For most common cases use
|
||
@code{with_mutex/2}, wich provides a safer way for handling prolog-level
|
||
mutexes.
|
||
|
||
@item mutex_trylock(+@var{MutexId})
|
||
@findex mutex_trylock/1
|
||
@snindex mutex_trylock/1
|
||
@cnindex mutex_trylock/1
|
||
As mutex_lock/1, but if the mutex is held by another thread, this
|
||
predicates fails immediately.
|
||
|
||
@item mutex_unlock(+@var{MutexId})
|
||
@findex mutex_unlock/1
|
||
@snindex mutex_unlock/1
|
||
@cnindex mutex_unlock/1
|
||
Unlock the mutex. This can only be called if the mutex is held by the
|
||
calling thread. If this is not the case, a @code{permission_error}
|
||
exception is raised.
|
||
|
||
@item mutex_unlock_all
|
||
@findex mutex_unlock_all/0
|
||
@snindex mutex_unlock_all/0
|
||
@cnindex mutex_unlock_all/0
|
||
Unlock all mutexes held by the current thread. This call is especially
|
||
useful to handle thread-termination using @code{abort/0} or exceptions. See
|
||
also @code{thread_signal/2}.
|
||
|
||
@item current_mutex(?@var{MutexId}, ?@var{ThreadId}, ?@var{Count})
|
||
@findex current_mutex/3
|
||
@snindex current_mutex/3
|
||
@cnindex current_mutex/3
|
||
Enumerates all existing mutexes. If the mutex is held by some thread,
|
||
@var{ThreadId} is unified with the identifier of te holding thread and
|
||
@var{Count} with the recursive count of the mutex. Otherwise,
|
||
@var{ThreadId} is @code{[]} and @var{Count} is 0.
|
||
@end table
|
||
|
||
|
||
@node Parallelism, Tabling, Threads, Extensions
|
||
@chapter Parallelism
|
||
|
||
@cindex parallelism
|
||
@cindex or-parallelism
|
||
There has been a sizeable amount of work on an or-parallel
|
||
implementation for YAP, called @strong{YapOr}. Most of this work has
|
||
been performed by Ricardo Rocha. In this system parallelism is exploited
|
||
implicitly by running several alternatives in or-parallel. This option
|
||
can be enabled from the @code{configure} script or by checking the
|
||
system's @code{Makefile}.
|
||
|
||
@strong{YapOr} is still a very experimental system, going through rapid
|
||
development. The following restrictions are of note:
|
||
|
||
@itemize @bullet
|
||
@item @strong{YapOr} currently only supports the Linux/X86 and SPARC/Solaris
|
||
platforms. Porting to other Unix-like platforms should be straightforward.
|
||
|
||
@item @strong{YapOr} does not support parallel updates to the
|
||
data-base.
|
||
|
||
@item @strong{YapOr} does not support opening or closing of streams during
|
||
parallel execution.
|
||
|
||
@item Garbage collection and stack shifting are not supported in
|
||
@strong{YapOr}.
|
||
|
||
@item Built-ins that cause side-effects can only be executed when
|
||
left-most in the search-tree. There are no primitives to provide
|
||
asynchronous or cavalier execution of these built-ins, as in Aurora or
|
||
Muse.
|
||
|
||
@item YAP does not support voluntary suspension of work.
|
||
@end itemize
|
||
|
||
We expect that some of these restrictions will be removed in future
|
||
releases.
|
||
|
||
@node Tabling, Low Level Tracing, Parallelism , Extensions
|
||
@chapter Tabling
|
||
@cindex tabling
|
||
|
||
@strong{YapTab} is the tabling engine that extends Yap's execution
|
||
model to support tabled evaluation for definite programs. YapTab was
|
||
implemented by Ricardo Rocha and its implementation is largely based
|
||
on the ground-breaking design of the XSB Prolog system, which
|
||
implements the SLG-WAM. Tables are implemented using tries and YapTab
|
||
supports the dynamic intermixing of batched scheduling and local
|
||
scheduling at the subgoal level. Currently, the following restrictions
|
||
are of note:
|
||
@itemize @bullet
|
||
@item YapTab does not handle tabled predicates with loops through negation (undefined behaviour).
|
||
@item YapTab does not handle tabled predicates with cuts (undefined behaviour).
|
||
@item YapTab does not support coroutining (configure error).
|
||
@item YapTab does not support tabling dynamic predicates (permission error).
|
||
@end itemize
|
||
|
||
To experiment with YapTab use @code{--enable-tabling} in the configure
|
||
script or add @code{-DTABLING} to @code{YAP_EXTRAS} in the system's
|
||
@code{Makefile}. We next describe the set of built-ins predicates
|
||
designed to interact with YapTab and control tabled execution:
|
||
|
||
@table @code
|
||
@item table +@var{P}
|
||
@findex table/1
|
||
@snindex table/1
|
||
@cnindex table/1
|
||
Declares predicate @var{P} (or a list of predicates
|
||
@var{P1},...,@var{Pn} or [@var{P1},...,@var{Pn}]) as a tabled
|
||
predicate. @var{P} must be written in the form
|
||
@var{name/arity}. Examples:
|
||
@example
|
||
:- table son/3.
|
||
:- table father/2.
|
||
:- table mother/2.
|
||
@end example
|
||
@noindent or
|
||
@example
|
||
:- table son/3, father/2, mother/2.
|
||
@end example
|
||
@noindent or
|
||
@example
|
||
:- table [son/3, father/2, mother/2].
|
||
@end example
|
||
|
||
@item is_tabled(+@var{P})
|
||
@findex is_tabled/1
|
||
@snindex is_tabled/1
|
||
@cnindex is_tabled/1
|
||
Succeeds if the predicate @var{P} (or a list of predicates
|
||
@var{P1},...,@var{Pn} or [@var{P1},...,@var{Pn}]), of the form
|
||
@var{name/arity}, is a tabled predicate.
|
||
|
||
@item tabling_mode(+@var{P},?@var{Mode})
|
||
@findex tabling_mode/2
|
||
@snindex tabling_mode/2
|
||
@cnindex tabling_mode/2
|
||
Sets or reads the default tabling mode for a tabled predicate @var{P}
|
||
(or a list of predicates @var{P1},...,@var{Pn} or
|
||
[@var{P1},...,@var{Pn}]). The list of @var{Mode} options includes:
|
||
@table @code
|
||
@item batched
|
||
Defines that, by default, batched scheduling is the scheduling
|
||
strategy to be used to evaluated calls to predicate @var{P}.
|
||
@item local
|
||
Defines that, by default, local scheduling is the scheduling
|
||
strategy to be used to evaluated calls to predicate @var{P}.
|
||
@item exec_answers
|
||
Defines that, by default, when a call to predicate @var{P} is
|
||
already evaluated (completed), answers are obtained by executing
|
||
compiled WAM-like code directly from the trie data
|
||
structure. This reduces the loading time when backtracking, but
|
||
the order in which answers are obtained is undefined.
|
||
@item load_answers
|
||
Defines that, by default, when a call to predicate @var{P} is
|
||
already evaluated (completed), answers are obtained (as a
|
||
consumer) by loading them from the trie data structure. This
|
||
guarantees that answers are obtained in the same order as they
|
||
were found. Somewhat less efficient but creates less choice-points.
|
||
@end table
|
||
The default tabling mode for a new tabled predicate is @code{batched}
|
||
and @code{exec_answers}. To set the tabling mode for all predicates at
|
||
once you can use the @code{yap_flag/2} predicate as described next.
|
||
|
||
@item yap_flag(tabling_mode,?@var{Mode})
|
||
@findex tabling_mode (yap_flag/2 option)
|
||
Sets or reads the tabling mode for all tabled predicates. The list of
|
||
@var{Mode} options includes:
|
||
@table @code
|
||
@item default
|
||
Defines that (i) all calls to tabled predicates are evaluated
|
||
using the predicate default mode, and that (ii) answers for all
|
||
completed calls are obtained by using the predicate default mode.
|
||
@item batched
|
||
Defines that all calls to tabled predicates are evaluated using
|
||
batched scheduling. This option ignores the default tabling mode
|
||
of each predicate.
|
||
@item local
|
||
Defines that all calls to tabled predicates are evaluated using
|
||
local scheduling. This option ignores the default tabling mode
|
||
of each predicate.
|
||
@item exec_answers
|
||
Defines that answers for all completed calls are obtained by
|
||
executing compiled WAM-like code directly from the trie data
|
||
structure. This option ignores the default tabling mode
|
||
of each predicate.
|
||
@item load_answers
|
||
Defines that answers for all completed calls are obtained by
|
||
loading them from the trie data structure. This option ignores
|
||
the default tabling mode of each predicate.
|
||
@end table
|
||
|
||
@item abolish_table(+@var{P})
|
||
@findex abolish_table/1
|
||
@snindex abolish_table/1
|
||
@cnindex abolish_table/1
|
||
Removes all the entries from the table space for predicate @var{P} (or
|
||
a list of predicates @var{P1},...,@var{Pn} or
|
||
[@var{P1},...,@var{Pn}]). The predicate remains as a tabled predicate.
|
||
|
||
@item abolish_all_tables/0
|
||
@findex abolish_all_tables/0
|
||
@snindex abolish_all_tables/0
|
||
@cnindex abolish_all_tables/0
|
||
Removes all the entries from the table space for all tabled
|
||
predicates. The predicates remain as tabled predicates.
|
||
|
||
@item show_table(+@var{P})
|
||
@findex show_table/1
|
||
@snindex show_table/1
|
||
@cnindex show_table/1
|
||
Prints table contents (subgoals and answers) for predicate @var{P}
|
||
(or a list of predicates @var{P1},...,@var{Pn} or
|
||
[@var{P1},...,@var{Pn}]).
|
||
|
||
@item table_statistics(+@var{P})
|
||
@findex table_statistics/1
|
||
@snindex table_statistics/1
|
||
@cnindex table_statistics/1
|
||
Prints table statistics (subgoals and answers) for predicate @var{P}
|
||
(or a list of predicates @var{P1},...,@var{Pn} or
|
||
[@var{P1},...,@var{Pn}]).
|
||
|
||
@item tabling_statistics/0
|
||
@findex tabling_statistics/0
|
||
@snindex tabling_statistics/0
|
||
@cnindex tabling_statistics/0
|
||
Prints statistics on space used by all tables.
|
||
@end table
|
||
|
||
|
||
@node Low Level Tracing, Low Level Profiling, Tabling, Extensions
|
||
@chapter Tracing at Low Level
|
||
|
||
It is possible to follow the flow at abstract machine level if
|
||
YAP is compiled with the flag @code{LOW_LEVEL_TRACER}. Note
|
||
that this option is of most interest to implementers, as it quickly generates
|
||
an huge amount of information.
|
||
|
||
Low level tracing can be toggled from an interrupt handler by using the
|
||
option @code{T}. There are also two built-ins that activate and
|
||
deactivate low level tracing:
|
||
|
||
@table @code
|
||
@item start_low_level_trace
|
||
@findex start_low_level_trace/0
|
||
@snindex start_low_level_trace/0
|
||
@cnindex start_low_level_trace/0
|
||
Begin display of messages at procedure entry and retry.
|
||
|
||
@item stop_low_level_trace
|
||
@findex start_low_level_trace/0
|
||
@snindex start_low_level_trace/0
|
||
@cnindex start_low_level_trace/0
|
||
Stop display of messages at procedure entry and retry.
|
||
@end table
|
||
|
||
Note that this compile-time option will slow down execution.
|
||
|
||
@node Low Level Profiling, , Low Level Tracing, Extensions
|
||
@chapter Profiling the Abstract Machine
|
||
|
||
Implementors may be interested in detecting on which abstract machine
|
||
instructions are executed by a program. The @code{ANALYST} flag can give
|
||
WAM level information. Note that this option slows down execution very
|
||
substantially, and is only of interest to developers of the system
|
||
internals, or to system debuggers.
|
||
|
||
@table @code
|
||
@item reset_op_counters
|
||
@findex reset_op_counters/0
|
||
@snindex reset_op_counters/0
|
||
@cnindex reset_op_counters/0
|
||
Reinitialize all counters.
|
||
|
||
@item show_op_counters(+@var{A})
|
||
@findex show_op_counters/1
|
||
@snindex show_op_counters/1
|
||
@cnindex show_op_counters/1
|
||
Display the current value for the counters, using label @var{A}. The
|
||
label must be an atom.
|
||
|
||
@item show_ops_by_group(+@var{A})
|
||
@findex show_ops_by_group/1
|
||
@snindex show_ops_by_group/1
|
||
@cnindex show_ops_by_group/1
|
||
Display the current value for the counters, organized by groups, using
|
||
label @var{A}. The label must be an atom.
|
||
|
||
@end table
|
||
|
||
@node Debugging,Efficiency,Extensions,Top
|
||
@chapter Debugging
|
||
|
||
@menu
|
||
* Deb Preds:: Debugging Predicates
|
||
* Deb Interaction:: Interacting with the debugger
|
||
@end menu
|
||
|
||
@node Deb Preds, Deb Interaction, , Debugging
|
||
@section Debugging Predicates
|
||
|
||
The following predicates are available to control the debugging of
|
||
programs:
|
||
|
||
@table @code
|
||
@item debug
|
||
@findex debug/0
|
||
@saindex debug/0
|
||
@cyindex debug/0
|
||
Switches the debugger on.
|
||
|
||
@item debugging
|
||
@findex debugging/0
|
||
@syindex debugging/0
|
||
@cyindex debugging/0
|
||
Outputs status information about the debugger which includes the leash
|
||
mode and the existing spy-points, when the debugger is on.
|
||
|
||
@item nodebug
|
||
@findex nodebug/0
|
||
@syindex nodebug/0
|
||
@cyindex nodebug/0
|
||
Switches the debugger off.
|
||
|
||
@item spy +@var{P}
|
||
@findex spy/1
|
||
@syindex spy/1
|
||
@cyindex spy/1
|
||
Sets spy-points on all the predicates represented by
|
||
@var{P}. @var{P} can either be a single specification or a list of
|
||
specifications. Each one must be of the form @var{Name/Arity}
|
||
or @var{Name}. In the last case all predicates with the name
|
||
@var{Name} will be spied. As in C-Prolog, system predicates and
|
||
predicates written in C, cannot be spied.
|
||
|
||
@item nospy +@var{P}
|
||
@findex nospy/1
|
||
@syindex nospy/1
|
||
@cyindex nospy/1
|
||
Removes spy-points from all predicates specified by @var{P}.
|
||
The possible forms for @var{P} are the same as in @code{spy P}.
|
||
|
||
@item nospyall
|
||
@findex nospyall/0
|
||
@syindex nospyall/0
|
||
@cnindex nospyall/0
|
||
Removes all existing spy-points.
|
||
|
||
@item notrace
|
||
Switches off the debugger and stops tracing.
|
||
|
||
@item leash(+@var{M})
|
||
@findex leash/1
|
||
@syindex leash/1
|
||
@cyindex leash/1
|
||
Sets leashing mode to @var{M}.
|
||
The mode can be specified as:
|
||
@table @code
|
||
@item full
|
||
prompt on Call, Exit, Redo and Fail
|
||
@item tight
|
||
prompt on Call, Redo and Fail
|
||
@item half
|
||
prompt on Call and Redo
|
||
@item loose
|
||
prompt on Call
|
||
@item off
|
||
never prompt
|
||
@item none
|
||
never prompt, same as @code{off}
|
||
@end table
|
||
@noindent
|
||
The initial leashing mode is @code{full}.
|
||
|
||
|
||
@noindent
|
||
The user may also specify directly the debugger ports
|
||
where he wants to be prompted. If the argument for leash
|
||
is a number @var{N}, each of lower four bits of the number is used to
|
||
control prompting at one the ports of the box model. The debugger will
|
||
prompt according to the following conditions:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
if @code{N/\ 1 =\= 0} prompt on fail
|
||
@item
|
||
if @code{N/\ 2 =\= 0} prompt on redo
|
||
@item
|
||
if @code{N/\ 4 =\= 0} prompt on exit
|
||
@item
|
||
if @code{N/\ 8 =\= 0} prompt on call
|
||
@end itemize
|
||
@noindent
|
||
Therefore, @code{leash(15)} is equivalent to @code{leash(full)} and
|
||
@code{leash(0)} is equivalent to @code{leash(off)}.
|
||
|
||
@noindent
|
||
Another way of using @code{leash} is to give it a list with the names of
|
||
the ports where the debugger should stop. For example,
|
||
@code{leash([call,exit,redo,fail])} is the same as @code{leash(full)} or
|
||
@code{leash(15)} and @code{leash([fail])} might be used instead of
|
||
@code{leash(1)}.
|
||
|
||
@item spy_write(+@var{Stream},Term)
|
||
@findex spy_write/2
|
||
@snindex spy_write/2
|
||
@cnindex spy_write/2
|
||
If defined by the user, this predicate will be used to print goals by
|
||
the debugger instead of @code{write/2}.
|
||
|
||
@item trace
|
||
Switches on the debugger and starts tracing.
|
||
|
||
@end table
|
||
|
||
|
||
@node Deb Interaction, , Deb Preds, Debugging
|
||
@section Interacting with the debugger
|
||
|
||
Debugging with YAP is similar to debugging with C-Prolog. Both
|
||
systems include a procedural debugger, based in the four port model. In
|
||
this model, execution is seen at the procedure level: each activation of
|
||
a procedure is seen as a box with control flowing into and out of that
|
||
box.
|
||
|
||
In the four port model control is caught at four key points: before
|
||
entering the procedure, after exiting the procedure (meaning successful
|
||
evaluation of all queries activated by the procedure), after backtracking but
|
||
before trying new alternative to the procedure and after failing the
|
||
procedure. Each one of these points is named a port:
|
||
|
||
@smallexample
|
||
@group
|
||
*--------------------------------------*
|
||
Call | | Exit
|
||
---------> + descendant(X,Y) :- offspring(X,Y). + --------->
|
||
| |
|
||
| descendant(X,Z) :- |
|
||
<--------- + offspring(X,Y), descendant(Y,Z). + <---------
|
||
Fail | | Redo
|
||
*--------------------------------------*
|
||
@end group
|
||
@end smallexample
|
||
|
||
@table @code
|
||
|
||
@item Call
|
||
The call port is activated before initial invocation of
|
||
procedure. Afterwards, execution will try to match the goal with the
|
||
head of existing clauses for the procedure.
|
||
@item Exit
|
||
This port is activated if the procedure succeeds.
|
||
Control will now leave the procedure and return to its ancestor.
|
||
@item Redo
|
||
if the goal, or goals, activated after the call port
|
||
fail then backtracking will eventually return control to this procedure
|
||
through the redo port.
|
||
@item Fail
|
||
If all clauses for this predicate fail, then the
|
||
invocation fails, and control will try to redo the ancestor of this
|
||
invocation.
|
||
@end table
|
||
|
||
To start debugging, the user will usually spy the relevant procedures,
|
||
entering debug mode, and start execution of the program. When finding
|
||
the first spy-point, YAP's debugger will take control and show a
|
||
message like:
|
||
|
||
@example
|
||
* (1) call: quicksort([1,2,3],_38) ?
|
||
@end example
|
||
|
||
The debugger message will be shown while creeping, or at spy-points,
|
||
and it includes four or five fields:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
The first three characters are used to point out special states of the
|
||
debugger. If the port is exit and the first character is '?', the
|
||
current call still has alternatives to be tried. If the second character is a @code{*}, execution is at a
|
||
spy-point. If the third character is a @code{>}, execution has returned
|
||
either from a skip, a fail or a redo command.
|
||
@item
|
||
The second field is the activation number, and uniquely identifies the
|
||
activation. The number will start from 1 and will be incremented for
|
||
each activation found by the debugger.
|
||
@item
|
||
In the third field, the debugger shows the active port.
|
||
@item
|
||
The fourth field is the goal. The goal is written by @code{write/1}.
|
||
@end itemize
|
||
|
||
If the active port is leashed, the debugger will prompt the user with a
|
||
@code{?}, and wait for a command. A debugger command is just a
|
||
character, followed by a return. By default, only the call and redo
|
||
entries are leashed, but the @code{leash/1} predicate can be used in
|
||
order to make the debugger stop where needed.
|
||
|
||
There are several commands available, but the user only needs to
|
||
remember the help command, which is @code{h}. This command shows all the
|
||
available options, which are:
|
||
@table @code
|
||
@item c - creep
|
||
this command makes YAP continue execution and stop at the next
|
||
leashed port.
|
||
@item return - creep
|
||
the same as c
|
||
@item l - leap
|
||
YAP will continue execution until a port of a spied predicate
|
||
is found;
|
||
@item k - quasi-leap
|
||
similar to leap but faster since the computation history is
|
||
not kept; useful when leap becomes too slow.
|
||
@item s - skip
|
||
YAP will continue execution without showing any messages until
|
||
returning to the current activation. Spy-points will be ignored in this
|
||
mode. This command is meaningless, and therefore illegal, in the fail
|
||
and exit ports.
|
||
@item t - fast-skip
|
||
similar to skip but faster since the computation history is not
|
||
kept; useful when skip becomes too slow.
|
||
@item q - quasi-leap
|
||
YAP will continue execution until a port of a spied
|
||
predicate is found or until returning to the current activation.
|
||
@item f - fail
|
||
forces YAP to fail the goal proceeding directly to the fail port.
|
||
The command is not available in the fail port.
|
||
@item r - retry
|
||
after this command, YAP will retry the present goal, and so go
|
||
back to the call port. Note that any side effects of the goal will not
|
||
be undone. This command is not available at the call port.
|
||
@item a - abort
|
||
execution will be aborted, and the interpreter will return to the
|
||
top-level.
|
||
@item n - nodebug
|
||
stop debugging but continue execution. The command will clear all active
|
||
spy-points, leave debugging mode and continue execution.
|
||
@item e - exit
|
||
leave YAP.
|
||
@item h - help
|
||
show the debugger commands.
|
||
@item ! Query
|
||
execute a query. YAP will not show the result of the query.
|
||
@item b - break
|
||
break active execution and launch a break level. This is the same as !
|
||
break.
|
||
@item + - spy this goal
|
||
start spying the active goal. The same as @code{! spy G} where @var{G}
|
||
is the active goal.
|
||
@item - - nospy this goal
|
||
stop spying the active goal. The same as @code{! nospy G} where @var{G} is
|
||
the active goal.
|
||
@item p - print
|
||
shows the active goal using print/1
|
||
@item d - display
|
||
shows the active goal using display/1
|
||
@item <Depth - debugger write depth
|
||
sets the maximum write depth, both for composite terms and lists, that
|
||
will be used by the debugger. For more
|
||
information about @code{write_depth/2} (@pxref{I/O Control}).
|
||
@item < - full term
|
||
resets to the default of ten the debugger's maximum write depth. For
|
||
more information about @code{write_depth/2} (@pxref{I/O Control}).
|
||
@item A - alternatives
|
||
show the list of backtrack points in the current execution.
|
||
@end table
|
||
|
||
The debugging information, when fast-skip @code{quasi-leap} is used, will
|
||
be lost.
|
||
|
||
@node Efficiency, C-Interface, Debugging, Top
|
||
|
||
@chapter Efficiency Considerations
|
||
|
||
We next discuss several issues on trying to make Prolog programs run
|
||
fast in YAP. We assume two different programming styles:
|
||
|
||
@table @bullet
|
||
@item Execution of @emph{deterministic} programs often
|
||
boils down to a recursive loop of the form:
|
||
@example
|
||
loop(Env) :-
|
||
do_something(Env,NewEnv),
|
||
loop(NewEnv).
|
||
@end example
|
||
|
||
@end table
|
||
|
||
@section Deterministic Programs
|
||
|
||
@section Non-Deterministic Programs
|
||
|
||
@section Data-Base Operations
|
||
|
||
@section Indexing
|
||
|
||
@section Profiling
|
||
|
||
The indexation mechanism restricts the set of clauses to be tried in a
|
||
procedure by using information about the status of a selected argument of
|
||
the goal (in YAP, as in most compilers, the first argument).
|
||
This argument
|
||
is then used as a key, selecting a restricted set of a clauses from all the
|
||
clauses forming the procedure.
|
||
|
||
As an example, the two clauses for concatenate:
|
||
|
||
@example
|
||
concatenate([],L,L).
|
||
concatenate([H|T],A,[H|NT]) :- concatenate(T,A,NT).
|
||
@end example
|
||
|
||
If the first argument for the goal is a list, then only the second clause
|
||
is of interest. If the first argument is the nil atom, the system needs to
|
||
look only for the first clause. The indexation generates instructions that
|
||
test the value of the first argument, and then proceed to a selected clause,
|
||
or group of clauses.
|
||
|
||
Note that if the first argument was a free variable, then both clauses
|
||
should be tried. In general, indexation will not be useful if the first
|
||
argument is a free variable.
|
||
|
||
When activating a predicate, a Prolog system needs to store state
|
||
information. This information, stored in a structure known as choice point
|
||
or fail point, is necessary when backtracking to other clauses for the
|
||
predicate. The operations of creating and using a choice point are very
|
||
expensive, both in the terms of space used and time spent.
|
||
Creating a choice point is not necessary if there is only a clause for
|
||
the predicate as there are no clauses to backtrack to. With indexation, this
|
||
situation is extended: in the example, if the first argument was the atom
|
||
nil, then only one clause would really be of interest, and it is pointless to
|
||
create a choice point. This feature is even more useful if the first argument
|
||
is a list: without indexation, execution would try the first clause, creating
|
||
a choice point. The clause would fail, the choice point would then be used to
|
||
restore the previous state of the computation and the second clause would
|
||
be tried. The code generated by the indexation mechanism would behave
|
||
much more efficiently: it would test the first argument and see whether it
|
||
is a list, and then proceed directly to the second clause.
|
||
|
||
An important side effect concerns the use of "cut". In the above
|
||
example, some programmers would use a "cut" in the first clause just to
|
||
inform the system that the predicate is not backtrackable and force the
|
||
removal the choice point just created. As a result, less space is needed but
|
||
with a great loss in expressive power: the "cut" would prevent some uses of
|
||
the procedure, like generating lists through backtracking. Of course, with
|
||
indexation the "cut" becomes useless: the choice point is not even created.
|
||
|
||
Indexation is also very important for predicates with a large number
|
||
of clauses that are used like tables:
|
||
|
||
@example
|
||
logician(aristhoteles,greek).
|
||
logician(frege,german).
|
||
logician(russel,english).
|
||
logician(godel,german).
|
||
logician(whitehead,english).
|
||
@end example
|
||
|
||
An interpreter like C-Prolog, trying to answer the query:
|
||
|
||
@example
|
||
?- logician(godel,X).
|
||
@end example
|
||
|
||
@noindent
|
||
would blindly follow the standard Prolog strategy, trying first the
|
||
first clause, then the second, the third and finally finding the
|
||
relevant clause. Also, as there are some more clauses after the
|
||
important one, a choice point has to be created, even if we know the
|
||
next clauses will certainly fail. A "cut" would be needed to prevent
|
||
some possible uses for the procedure, like generating all logicians. In
|
||
this situation, the indexing mechanism generates instructions that
|
||
implement a search table. In this table, the value of the first argument
|
||
would be used as a key for fast search of possibly matching clauses. For
|
||
the query of the last example, the result of the search would be just
|
||
the fourth clause, and again there would be no need for a choice point.
|
||
|
||
If the first argument is a complex term, indexation will select clauses
|
||
just by testing its main functor. However, there is an important
|
||
exception: if the first argument of a clause is a list, the algorithm
|
||
also uses the list's head if not a variable. For instance, with the
|
||
following clauses,
|
||
|
||
@example
|
||
rules([],B,B).
|
||
rules([n(N)|T],I,O) :- rules_for_noun(N,I,N), rules(T,N,O).
|
||
rules([v(V)|T],I,O) :- rules_for_verb(V,I,N), rules(T,N,O).
|
||
rules([q(Q)|T],I,O) :- rules_for_qualifier(Q,I,N), rules(T,N,O).
|
||
@end example
|
||
@noindent
|
||
if the first argument of the goal is a list, its head will be tested, and only
|
||
the clauses matching it will be tried during execution.
|
||
|
||
Some advice on how to take a good advantage of this mechanism:
|
||
|
||
@itemize @bullet
|
||
|
||
@item
|
||
Try to make the first argument an input argument.
|
||
|
||
@item
|
||
Try to keep together all clauses whose first argument is not a
|
||
variable, that will decrease the number of tests since the other clauses are
|
||
always tried.
|
||
|
||
@item
|
||
Try to avoid predicates having a lot of clauses with the same key.
|
||
For instance, the procedure:
|
||
|
||
@end itemize
|
||
|
||
@example
|
||
type(n(mary),person).
|
||
type(n(john), person).
|
||
type(n(chair),object).
|
||
type(v(eat),active).
|
||
type(v(rest),passive).
|
||
@end example
|
||
|
||
@noindent
|
||
becomes more efficient with:
|
||
|
||
@example
|
||
type(n(N),T) :- type_of_noun(N,T).
|
||
type(v(V),T) :- type_of_verb(V,T).
|
||
|
||
type_of_noun(mary,person).
|
||
type_of_noun(john,person).
|
||
type_of_noun(chair,object).
|
||
|
||
type_of_verb(eat,active).
|
||
type_of_verb(rest,passive).
|
||
@end example
|
||
|
||
@node C-Interface,YapLibrary,Efficiency,Top
|
||
@chapter C Language interface to YAP
|
||
|
||
YAP provides the user with the necessary facilities for writing
|
||
predicates in a language other than prolog. Since, under Unix systems,
|
||
most language implementations are link-able to C, we will describe here
|
||
only the YAP interface to the C language.
|
||
|
||
Before describing in full detail how to interface to C code, we will examine
|
||
a brief example.
|
||
|
||
Assume the user requires a predicate @code{my_process_id(Id)} which succeeds
|
||
when @var{Id} unifies with the number of the process under which YAP is running.
|
||
|
||
In this case we will create a @code{my_process.c} file containing the
|
||
C-code described below.
|
||
|
||
@example
|
||
@cartouche
|
||
#include "Yap/YapInterface.h"
|
||
|
||
static int my_process_id(void)
|
||
@{
|
||
YAP_Term pid = YAP_MkIntTerm(getpid());
|
||
YAP_Term out = YAP_ARG1;
|
||
return(YAP_Unify(out,pid));
|
||
@}
|
||
|
||
void init_my_predicates()
|
||
@{
|
||
YAP_UserCPredicate("my_process_id",my_process_id,1);
|
||
@}
|
||
@end cartouche
|
||
@end example
|
||
|
||
The commands to compile the above file depend on the operating
|
||
system. Under Linux (i386 and Alpha) you should use:
|
||
@example
|
||
gcc -c -shared -fPIC my_process.c
|
||
ld -shared -o my_process.so my_process.o
|
||
@end example
|
||
@noindent
|
||
Under Solaris2 it is sufficient to use:
|
||
@example
|
||
gcc -fPIC -c my_process.c
|
||
@end example
|
||
@noindent
|
||
Under SunOS it is sufficient to use:
|
||
@example
|
||
gcc -c my_process.c
|
||
@end example
|
||
@noindent
|
||
Under Digital Unix you need to create a @code{so} file. Use:
|
||
@example
|
||
gcc tst.c -c -fpic
|
||
ld my_process.o -o my_process.so -shared -expect_unresolved '*'
|
||
@end example
|
||
@noindent
|
||
and replace my @code{process.so} for my @code{process.o} in the
|
||
remainder of the example.
|
||
@noindent
|
||
And could be loaded, under YAP, by executing the following prolog goal
|
||
@example
|
||
load_foreign_files(['my_process'],[],init_my_predicates).
|
||
@end example
|
||
Note that since Yap4.3.3 you should not give the suffix for object
|
||
files. YAP will deduce the correct suffix from the operating system it
|
||
is running under.
|
||
|
||
Yap4.3.3 now supports loading WIN/NT DLLs. Currently you must compile
|
||
YAP under cygwin to create a library yap.dll first. You can then use
|
||
this dll to create your own dlls. Have a look at the code in
|
||
library/regex to see how to create a dll under the cygwin/mingw32
|
||
environment.
|
||
|
||
After loading that file the following prolog goal
|
||
@example
|
||
my_process_id(N)
|
||
@end example
|
||
@noindent
|
||
would unify N with the number of the process under which Yap is running.
|
||
|
||
|
||
Having presented a full example, we will now examine in more detail the
|
||
contents of the C source code file presented above.
|
||
|
||
The include statement is used to make available to the C source code the
|
||
macros for the handling of prolog terms and also some Yap public
|
||
definitions.
|
||
|
||
The function @code{my_process_id} is the implementation, in C, of the
|
||
desired predicate. Note that it returns an integer denoting the success
|
||
of failure of the goal and also that it has no arguments even though the
|
||
predicate being defined has one.
|
||
In fact the arguments of a prolog predicate written in C are accessed
|
||
through macros, defined in the include file, with names @var{YAP_ARG1},
|
||
@var{YAP_ARG2}, ..., @var{YAP_ARG16} or with @var{YAP_A}(@var{N})
|
||
where @var{N} is the argument number (starting with 1). In the present
|
||
case the function uses just one local variable of type @code{YAP_Term}, the
|
||
type used for holding Yap terms, where the integer returned by the
|
||
standard unix function @code{getpid()} is stored as an integer term (the
|
||
conversion is done by @code{YAP_MkIntTerm(Int))}. Then it calls the
|
||
pre-defined routine @code{YAP_Unify(YAP_Term, YAP_Term)} which in turn returns an
|
||
integer denoting success or failure of the unification.
|
||
|
||
The role of the procedure @code{init_my_predicates} is to make known to
|
||
YAP, by calling @code{YAP_UserCPredicate}, the predicates being
|
||
defined in the file. This is in fact why, in the example above,
|
||
@code{init_my_predicates} was passed as the third argument to
|
||
@code{load_foreign_files}.
|
||
|
||
The rest of this appendix describes exhaustively how to interface C to YAP.
|
||
|
||
@menu
|
||
* Manipulating Terms:: Primitives available to the C programmer
|
||
* Unifying Terms:: How to Unify Two Prolog Terms
|
||
* Manipulating Strings:: From character arrays to Lists of codes and back
|
||
* Memory Allocation:: Stealing Memory From Yap
|
||
* Controlling Streams:: Control How Yap sees Streams
|
||
* Calling Yap From C:: From C to Yap to C to Yap
|
||
* Writing C:: Writing Predicates in C
|
||
* Loading Objects:: Loading Object Files
|
||
* Sav&Rest:: Saving and Restoring
|
||
* Yap4 Notes:: Changes in Foreign Predicates Interface
|
||
@end menu
|
||
|
||
@node Manipulating Terms, Unifying Terms, , C-Interface
|
||
@section Terms
|
||
|
||
This section provides information about the primitives available to the C
|
||
programmer for manipulating prolog terms.
|
||
|
||
Several C typedefs are included in the header file @code{yap/YapInterface.h} to
|
||
describe, in a portable way, the C representation of prolog terms.
|
||
The user should write is programs using this macros to ensure portability of
|
||
code across different versions of YAP.
|
||
|
||
|
||
The more important typedef is @var{YAP_Term} which is used to denote the
|
||
type of a prolog term.
|
||
|
||
Terms, from a point of view of the C-programmer, can be classified as
|
||
follows
|
||
@table @i
|
||
@item uninstantiated variables
|
||
@item instantiated variables
|
||
@item integers
|
||
@item floating-point numbers
|
||
@item database references
|
||
@item atoms
|
||
@item pairs (lists)
|
||
@item compound terms
|
||
@end table
|
||
|
||
@findex YAP_IsVarTerm (C-Interface function)
|
||
The primitive
|
||
@example
|
||
YAP_Bool YAP_IsVarTerm(YAP_Term @var{t})
|
||
@end example
|
||
@noindent
|
||
@findex YAP_IsNonVarTerm (C-Interface function)
|
||
returns true iff its argument is an uninstantiated variable. Conversely the
|
||
primitive
|
||
@example
|
||
YAP_Bool YAP_NonVarTerm(YAP_Term @var{t})
|
||
@end example
|
||
@noindent
|
||
returns true iff its argument is not a variable.
|
||
|
||
|
||
The user can create a new uninstantiated variable using the primitive
|
||
@example
|
||
YAP_Term YAP_MkVarTerm()
|
||
@end example
|
||
|
||
|
||
@findex YAP_IsIntTerm (C-Interface function)
|
||
@findex YAP_IsFloatTerm (C-Interface function)
|
||
@findex YAP_IsDBRefTerm (C-Interface function)
|
||
@findex YAP_IsAtomTerm (C-Interface function)
|
||
@findex YAP_IsPairTerm (C-Interface function)
|
||
@findex YAP_IsApplTerm (C-Interface function)
|
||
The following primitives can be used to discriminate among the different types
|
||
of non-variable terms:
|
||
@example
|
||
YAP_Bool YAP_IsIntTerm(YAP_Term @var{t})
|
||
YAP_Bool YAP_IsFloatTerm(YAP_Term @var{t})
|
||
YAP_Bool YAP_IsDbRefTerm(YAP_Term @var{t})
|
||
YAP_Bool YAP_IsAtomTerm(YAP_Term @var{t})
|
||
YAP_Bool YAP_IsPairTerm(YAP_Term @var{t})
|
||
YAP_Bool YAP_IsApplTerm(YAP_Term @var{t})
|
||
@end example
|
||
|
||
Next, we mention the primitives that allow one to destruct and construct
|
||
terms. All the above primitives ensure that their result is
|
||
@i{dereferenced}, i.e. that it is not a pointer to another term.
|
||
|
||
@findex YAP_MkIntTerm (C-Interface function)
|
||
@findex YAP_IntOfTerm (C-Interface function)
|
||
The following primitives are provided for creating an integer term from an
|
||
integer and to access the value of an integer term.
|
||
@example
|
||
YAP_Term YAP_MkIntTerm(YAP_Int @var{i})
|
||
YAP_Int YAP_IntOfTerm(YAP_Term @var{t})
|
||
@end example
|
||
@noindent
|
||
where @code{YAP_Int} is a typedef for the C integer type appropriate for
|
||
the machine or compiler in question (normally a long integer). The size
|
||
of the allowed integers is implementation dependent but is always
|
||
greater or equal to 24 bits: usually 32 bits on 32 bit machines, and 64
|
||
on 64 bit machines.
|
||
|
||
@findex YAP_MkFloatTerm (C-Interface function)
|
||
@findex YAP_FloatOfTerm (C-Interface function)
|
||
The two following primitives play a similar role for floating-point terms
|
||
@example
|
||
YAP_Term YAP_MkFloatTerm(YAP_flt @var{double})
|
||
YAP_flt YAP_FloatOfTerm(YAP_Term @var{t})
|
||
@end example
|
||
@noindent
|
||
where @code{flt} is a typedef for the appropriate C floating point type,
|
||
nowadays a @code{double}
|
||
|
||
@findex YAP_IsBigNumTerm (C-Interface function)
|
||
@findex YAP_MkBigNumTerm (C-Interface function)
|
||
@findex YAP_BigNumOfTerm (C-Interface function)
|
||
The following primitives are provided for verifying whether a term is
|
||
a big int, creating a term from a big integer and to access the value
|
||
of a big int from a term.
|
||
@example
|
||
YAP_Bool YAP_IsBigNumTerm(YAP_Term @var{t})
|
||
YAP_Term YAP_MkBigNumTerm(void *@var{b})
|
||
void *YAP_BigNumOfTerm(YAP_Term @var{t}, void *@var{b})
|
||
@end example
|
||
@noindent
|
||
YAP must support bignum for the configuration you are using (check the
|
||
YAP configuration and setup). For now, Yap only supports the GNU GMP
|
||
library, and @code{void *} will be a cast for @code{mpz_t}. Notice
|
||
that @code{YAP_BigNumOfTerm} requires the number to be already
|
||
initialised. As an example, we show how to print a bignum:
|
||
|
||
@example
|
||
static int
|
||
p_print_bignum(void)
|
||
@{
|
||
mpz_t mz;
|
||
if (!YAP_IsBigNumTerm(YAP_ARG1))
|
||
return FALSE;
|
||
|
||
mpz_init(mz);
|
||
YAP_BigNumOfTerm(YAP_ARG1, mz);
|
||
gmp_printf("Shows up as %Zd\n", mz);
|
||
mpz_clear(mz);
|
||
return TRUE;
|
||
@}
|
||
@end example
|
||
|
||
|
||
Currently, no primitives are supplied to users for manipulating data base
|
||
references.
|
||
|
||
@findex YAP_MkAtomTerm (C-Interface function)
|
||
@findex YAP_AtomOfTerm (C-Interface function)
|
||
A special typedef @code{YAP_Atom} is provided to describe prolog
|
||
@i{atoms} (symbolic constants). The two following primitives can be used
|
||
to manipulate atom terms
|
||
@example
|
||
YAP_Term YAP_MkAtomTerm(YAP_Atom at)
|
||
YAP_Atom YAP_AtomOfTerm(YAP_Term @var{t})
|
||
@end example
|
||
@noindent
|
||
@findex YAP_LookupAtom (C-Interface function)
|
||
@findex YAP_FullLookupAtom (C-Interface function)
|
||
@findex YAP_AtomName (C-Interface function)
|
||
The following primitives are available for associating atoms with their
|
||
names
|
||
@example
|
||
YAP_Atom YAP_LookupAtom(char * @var{s})
|
||
YAP_Atom YAP_FullLookupAtom(char * @var{s})
|
||
char *YAP_AtomName(YAP_Atom @var{t})
|
||
@end example
|
||
The function @code{YAP_LookupAtom} looks up an atom in the standard hash
|
||
table. The function @code{YAP_FullLookupAtom} will also search if the
|
||
atom had been "hidden": this is useful for system maintenance from C
|
||
code. The functor @code{YAP_AtomName} returns a pointer to the string
|
||
for the atom.
|
||
|
||
@findex YAP_MkPairTerm (C-Interface function)
|
||
@findex YAP_MkNewPairTerm (C-Interface function)
|
||
@findex YAP_HeadOfTerm (C-Interface function)
|
||
@findex YAP_TailOfTerm (C-Interface function)
|
||
A @i{pair} is a Prolog term which consists of a tuple of two prolog
|
||
terms designated as the @i{head} and the @i{tail} of the term. Pairs are
|
||
most often used to build @emph{lists}. The following primitives can be
|
||
used to manipulate pairs:
|
||
@example
|
||
YAP_Term YAP_MkPairTerm(YAP_Term @var{Head}, YAP_Term @var{Tail})
|
||
YAP_Term YAP_MkNewPairTerm(void)
|
||
YAP_Term YAP_HeadOfTerm(YAP_Term @var{t})
|
||
YAP_Term YAP_TailOfTerm(YAP_Term @var{t})
|
||
@end example
|
||
One can construct a new pair from two terms, or one can just build a
|
||
pair whose head and tail are new unbound variables. Finally, one can
|
||
fetch the head or the tail.
|
||
|
||
@findex YAP_MkApplTerm (C-Interface function)
|
||
@findex YAP_MkNewApplTerm (C-Interface function)
|
||
@findex YAP_ArgOfTerm (C-Interface function)
|
||
@findex YAP_FunctorOfTerm (C-Interface function)
|
||
A @i{compound} term consists of a @i{functor} and a sequence of terms with
|
||
length equal to the @i{arity} of the functor. A functor, described in C by
|
||
the typedef @code{Functor}, consists of an atom and of an integer.
|
||
The following primitives were designed to manipulate compound terms and
|
||
functors
|
||
@example
|
||
YAP_Term YAP_MkApplTerm(YAP_Functor @var{f}, unsigned long int @var{n}, YAP_Term[] @var{args})
|
||
YAP_Term YAP_MkNewApplTerm(YAP_Functor @var{f}, int @var{n})
|
||
YAP_Term YAP_ArgOfTerm(int argno,YAP_Term @var{ts})
|
||
YAP_Functor YAP_FunctorOfTerm(YAP_Term @var{ts})
|
||
@end example
|
||
@noindent
|
||
The @code{YAP_MkApplTerm} function constructs a new term, with functor
|
||
@var{f} (of arity @var{n}), and using an array @var{args} of @var{n}
|
||
terms with @var{n} equal to the arity of the
|
||
functor. @code{YAP_MkNewApplTerm} builds up a compound term whose
|
||
arguments are unbound variables. @code{YAP_ArgOfTerm} gives an argument
|
||
to a compound term. @code{argno} should be greater or equal to 1 and
|
||
less or equal to the arity of the functor.
|
||
|
||
YAP allows one to manipulate the functors of compound term. The function
|
||
@code{YAP_FunctorOfTerm} allows one to obtain a variable of type
|
||
@code{YAP_Functor} with the functor to a term. The following functions
|
||
then allow one to construct functors, and to obtain their name and arity.
|
||
|
||
@findex YAP_MkFunctor (C-Interface function)
|
||
@findex YAP_NameOfFunctor (C-Interface function)
|
||
@findex YAP_ArityOfFunctor (C-Interface function)
|
||
@example
|
||
YAP_Functor YAP_MkFunctor(YAP_Atom @var{a},unsigned long int @var{arity})
|
||
YAP_Atom YAP_NameOfFunctor(YAP_Functor @var{f})
|
||
YAP_Int YAP_ArityOfFunctor(YAP_Functor @var{f})
|
||
@end example
|
||
@noindent
|
||
|
||
Note that the functor is essentially a pair formed by an atom, and
|
||
arity.
|
||
|
||
@node Unifying Terms, Manipulating Strings, Manipulating Terms, C-Interface
|
||
@section Unification
|
||
|
||
@findex YAP_Unify (C-Interface function)
|
||
YAP provides a single routine to attempt the unification of two prolog
|
||
terms. The routine may succeed or fail:
|
||
@example
|
||
Int YAP_Unify(YAP_Term @var{a}, YAP_Term @var{b})
|
||
@end example
|
||
@noindent
|
||
The routine attempts to unify the terms @var{a} and
|
||
@var{b} returning @code{TRUE} if the unification succeeds and @code{FALSE}
|
||
otherwise.
|
||
|
||
@node Manipulating Strings, Memory Allocation, Unifying Terms, C-Interface
|
||
@section Strings
|
||
|
||
@findex YAP_StringToBuffer (C-Interface function)
|
||
The YAP C-interface now includes an utility routine to copy a string
|
||
represented as a list of a character codes to a previously allocated buffer
|
||
@example
|
||
int YAP_StringToBuffer(YAP_Term @var{String}, char *@var{buf}, unsigned int @var{bufsize})
|
||
@end example
|
||
@noindent
|
||
The routine copies the list of character codes @var{String} to a
|
||
previously allocated buffer @var{buf}. The string including a
|
||
terminating null character must fit in @var{bufsize} characters,
|
||
otherwise the routine will simply fail. The @var{StringToBuffer} routine
|
||
fails and generates an exception if @var{String} is not a valid string.
|
||
|
||
@findex YAP_BufferToString (C-Interface function)
|
||
@findex YAP_BufferToAtomList (C-Interface function)
|
||
The C-interface also includes utility routines to do the reverse, that
|
||
is, to copy a from a buffer to a list of character codes or to a list of
|
||
character atoms
|
||
@example
|
||
YAP_Term YAP_BufferToString(char *@var{buf})
|
||
YAP_Term YAP_BufferToAtomList(char *@var{buf})
|
||
@end example
|
||
@noindent
|
||
The user-provided string must include a terminating null character.
|
||
|
||
@findex YAP_ReadBuffer (C-Interface function)
|
||
The C-interface function calls the parser on a sequence of characters
|
||
stored at @var{buf} and returns the resulting term.
|
||
@example
|
||
YAP_Term YAP_ReadBuffer(char *@var{buf},YAP_Term *@var{error})
|
||
@end example
|
||
@noindent
|
||
The user-provided string must include a terminating null
|
||
character. Syntax errors will cause returning @code{FALSE} and binding
|
||
@var{error} to a Prolog term.
|
||
|
||
@node Memory Allocation, Controlling Streams, Manipulating Strings, C-Interface
|
||
@section Memory Allocation
|
||
|
||
@findex YAP_AllocSpaceFromYap (C-Interface function)
|
||
The next routine can be used to ask space from the Prolog data-base:
|
||
@example
|
||
void *YAP_AllocSpaceFromYap(int @var{size})
|
||
@end example
|
||
@noindent
|
||
The routine returns a pointer to a buffer allocated from the code area,
|
||
or @code{NULL} if sufficient space was not available.
|
||
|
||
@findex YAP_FreeSpaceFromYap (C-Interface function)
|
||
The space allocated with @code{YAP_AllocSpaceFromYap} can be released
|
||
back to Yap by using:
|
||
@example
|
||
void YAP_FreeSpaceFromYap(void *@var{buf})
|
||
@end example
|
||
@noindent
|
||
The routine releases a buffer allocated from the code area. The system
|
||
may crash if @code{buf} is not a valid pointer to a buffer in the code
|
||
area.
|
||
|
||
@node Controlling Streams, Calling Yap From C, Memory Allocation, C-Interface
|
||
@section Controlling Yap Streams from @code{C}
|
||
|
||
@findex YAP_StreamToFileNo (C-Interface function)
|
||
The C-Interface also provides the C-application with a measure of
|
||
control over the Yap Input/Output system. The first routine allows one
|
||
to find a file number given a current stream:
|
||
@example
|
||
int YAP_StreamToFileNo(YAP_Term @var{stream})
|
||
@end example
|
||
@noindent
|
||
This function gives the file descriptor for a currently available
|
||
stream. Note that null streams and in memory streams do not have
|
||
corresponding open streams, so the routine will return a
|
||
negative. Moreover, Yap will not be aware of any direct operations on
|
||
this stream, so information on, say, current stream position, may become
|
||
stale.
|
||
|
||
@findex YAP_CloseAllOpenStreams (C-Interface function)
|
||
A second routine that is sometimes useful is:
|
||
@example
|
||
void YAP_CloseAllOpenStreams(void)
|
||
@end example
|
||
@noindent
|
||
This routine closes the Yap Input/Output system except for the first
|
||
three streams, that are always associated with the three standard Unix
|
||
streams. It is most useful if you are doing @code{fork()}.
|
||
|
||
@findex YAP_OpenStream (C-Interface function)
|
||
The next routine allows a currently open file to become a stream. The
|
||
routine receives as arguments a file descriptor, the true file name as a
|
||
string, an atom with the user name, and a set of flags:
|
||
@example
|
||
void YAP_OpenStream(void *@var{FD}, char *@var{name}, YAP_Term @var{t}, int @var{flags})
|
||
@end example
|
||
@noindent
|
||
The available flags are @code{YAP_INPUT_STREAM},
|
||
@code{YAP_OUTPUT_STREAM}, @code{YAP_APPEND_STREAM},
|
||
@code{YAP_PIPE_STREAM}, @code{YAP_TTY_STREAM}, @code{YAP_POPEN_STREAM},
|
||
@code{YAP_BINARY_STREAM}, and @code{YAP_SEEKABLE_STREAM}. By default, the
|
||
stream is supposed to be at position 0. The argument @var{name} gives
|
||
the name by which YAP should know the new stream.
|
||
|
||
@node Calling Yap From C, Writing C, Controlling Streams, C-Interface
|
||
@section From @code{C} back to Prolog
|
||
|
||
@findex YAP_CallProlog (C-Interface function)
|
||
Newer versions of YAP allow for calling the Prolog interpreter from
|
||
@code{C}. One must first construct a goal @code{G}, and then it is
|
||
sufficient to perform:
|
||
@example
|
||
YAP_Bool YapCallProlog(YAP_Term @var{G})
|
||
@end example
|
||
@noindent
|
||
the result will be @code{FALSE}, if the goal failed, or @code{TRUE}, if
|
||
the goal succeeded. In this case, the variables in @var{G} will store
|
||
the values they have been unified with. Execution only proceeds until
|
||
finding the first solution to the goal, but you can call
|
||
@code{findall/3} or friends if you need all the solutions.
|
||
|
||
@node Writing C, Loading Objects, Calling Yap From C, C-Interface
|
||
@section Writing predicates in C
|
||
|
||
We will distinguish two kinds of predicates:
|
||
@table @i
|
||
@item @i{deterministic} predicates which either fail or succeed but are not
|
||
backtrackable, like the one in the introduction;
|
||
@item @i{backtrackable}
|
||
predicates which can succeed more than once.
|
||
@end table
|
||
|
||
@findex YAP_UserCPredicate (C-Interface function)
|
||
The first kind of predicates should be implemented as a C function with
|
||
no arguments which should return zero if the predicate fails and a
|
||
non-zero value otherwise. The predicate should be declared to
|
||
YAP, in the initialization routine, with a call to
|
||
@example
|
||
void YAP_UserCPredicate(char *@var{name}, YAP_Bool *@var{fn}(), unsigned long int @var{arity});
|
||
@end example
|
||
@noindent
|
||
where @var{name} is the name of the predicate, @var{fn} is the C function
|
||
implementing the predicate and @var{arity} is its arity.
|
||
|
||
@findex YAP_UserBackCPredicate (C-Interface function)
|
||
@findex YAP_PRESERVE_DATA (C-Interface function)
|
||
@findex YAP_PRESERVED_DATA (C-Interface function)
|
||
@findex YAP_cutsucceed (C-Interface function)
|
||
@findex YAP_cutfail (C-Interface function)
|
||
For the second kind of predicates we need two C functions. The first one
|
||
which is called when the predicate is first activated, and the second one
|
||
to be called on backtracking to provide (possibly) other solutions. Note
|
||
also that we normally also need to preserve some information to find out
|
||
the next solution.
|
||
|
||
In fact the role of the two functions can be better understood from the
|
||
following prolog definition
|
||
@example
|
||
p :- start.
|
||
p :- repeat,
|
||
continue.
|
||
@end example
|
||
@noindent
|
||
where @code{start} and @code{continue} correspond to the two C functions
|
||
described above.
|
||
|
||
|
||
As an example we will consider implementing in C a predicate @code{n100(N)}
|
||
which, when called with an instantiated argument should succeed if that
|
||
argument is a numeral less or equal to 100, and, when called with an
|
||
uninstantiated argument, should provide, by backtracking, all the positive
|
||
integers less or equal to 100.
|
||
|
||
To do that we first declare a structure, which can only consist
|
||
of prolog terms, containing the information to be preserved on backtracking
|
||
and a pointer variable to a structure of that type.
|
||
|
||
@example
|
||
#include "YapInterface.h"
|
||
|
||
static int start_n100(void);
|
||
static int continue_n100(void);
|
||
|
||
typedef struct @{
|
||
YAP_Term next_solution; /* the next solution */
|
||
@} n100_data_type;
|
||
|
||
n100_data_type *n100_data;
|
||
@end example
|
||
|
||
We now write the @code{C} function to handle the first call:
|
||
|
||
@example
|
||
static int start_n100(void)
|
||
@{
|
||
YAP_Term t = YAP_ARG1;
|
||
YAP_PRESERVE_DATA(n100_data,n100_data_type);
|
||
if(YAP_IsVarTerm(t)) @{
|
||
n100_data->next_solution = YAP_MkIntTerm(0);
|
||
return continue_n100();
|
||
@}
|
||
if(!YAP_IsIntTerm(t) || YAP_IntOfTerm(t)<0 || YAP_IntOfTerm(t)>100) @{
|
||
YAP_cut_fail();
|
||
@} else @{
|
||
YAP_cut_succeed();
|
||
@}
|
||
@}
|
||
|
||
@end example
|
||
|
||
The routine starts by getting the dereference value of the argument.
|
||
The call to @code{YAP_PRESERVE_DATA} is used to initialize the memory which will
|
||
hold the information to be preserved across backtracking. The first
|
||
argument is the variable we shall use, and the second its type. Note
|
||
that we can only use @code{YAP_PRESERVE_DATA} once, so often we will
|
||
want the variable to be a structure.
|
||
|
||
If the argument of the predicate is a variable, the routine initializes the
|
||
structure to be preserved across backtracking with the information
|
||
required to provide the next solution, and exits by calling @code{
|
||
continue_n100} to provide that solution.
|
||
|
||
If the argument was not a variable, the routine then checks if it was an
|
||
integer, and if so, if its value is positive and less than 100. In that
|
||
case it exits, denoting success, with @code{YAP_cut_succeed}, or
|
||
otherwise exits with @code{YAP_cut_fail} denoting failure.
|
||
|
||
The reason for using for using the functions @code{YAP_cut_succeed} and
|
||
@code{YAP_cut_fail} instead of just returning a non-zero value in the
|
||
first case, and zero in the second case, is that otherwise, if
|
||
backtracking occurred later, the routine @code{continue_n100} would be
|
||
called to provide additional solutions.
|
||
|
||
The code required for the second function is
|
||
@example
|
||
static int continue_n100(void)
|
||
@{
|
||
int n;
|
||
YAP_Term t;
|
||
YAP_Term sol = YAP_ARG1;
|
||
YAP_PRESERVED_DATA(n100_data,n100_data_type);
|
||
n = YAP_IntOfTerm(n100_data->next_solution);
|
||
if( n == 100) @{
|
||
t = YAP_MkIntTerm(n);
|
||
YAP_Unify(sol,t);
|
||
YAP_cut_succeed();
|
||
@}
|
||
else @{
|
||
YAP_Unify(sol,n100_data->next_solution);
|
||
n100_data->next_solution = YAP_MkIntTerm(n+1);
|
||
return(TRUE);
|
||
@}
|
||
@}
|
||
@end example
|
||
|
||
Note that again the macro @code{YAP_PRESERVED_DATA} is used at the
|
||
beginning of the function to access the data preserved from the previous
|
||
solution. Then it checks if the last solution was found and in that
|
||
case exits with @code{YAP_cut_succeed} in order to cut any further
|
||
backtracking. If this is not the last solution then we save the value
|
||
for the next solution in the data structure and exit normally with 1
|
||
denoting success. Note also that in any of the two cases we use the
|
||
function @code{YAP_unify} to bind the argument of the call to the value
|
||
saved in @code{ n100_state->next_solution}.
|
||
|
||
|
||
Note also that the only correct way to signal failure in a backtrackable
|
||
predicate is to use the @code{YAP_cut_fail} macro.
|
||
|
||
Backtrackable predicates should be declared to YAP, in a way
|
||
similar to what happened with deterministic ones, but using instead a
|
||
call to
|
||
@example
|
||
void YAP_UserBackCPredicate(char *@var{name},
|
||
int *@var{init}(), int *@var{cont}(),
|
||
unsigned long int @var{arity}, unsigned int @var{sizeof});
|
||
@end example
|
||
@noindent
|
||
where @var{name} is a string with the name of the predicate, @var{init} and
|
||
@var{cont} are the C functions used to start and continue the execution of
|
||
the predicate, @var{arity} is the predicate arity, and @var{sizeof} is
|
||
the size of the data to be preserved in the stack. In this example, we
|
||
would have something like
|
||
|
||
@example
|
||
void
|
||
init_n100(void)
|
||
@{
|
||
YAP_UserBackCPredicate("n100", start_n100, continue_n100, 1, 1);
|
||
@}
|
||
@end example
|
||
|
||
|
||
@node Loading Objects, Sav&Rest, Writing C, C-Interface
|
||
@section Loading Object Files
|
||
|
||
The primitive predicate
|
||
@example
|
||
load_foreign_files(@var{Files},@var{Libs},@var{InitRoutine})
|
||
@end example
|
||
@noindent
|
||
should be used, from inside YAP, to load object files produced by the C
|
||
compiler. The argument @var{ObjectFiles} should be a list of atoms
|
||
specifying the object files to load, @var{Libs} is a list (possibly
|
||
empty) of libraries to be passed to the unix loader (@code{ld}) and
|
||
InitRoutine is the name of the C routine (to be called after the files
|
||
are loaded) to perform the necessary declarations to YAP of the
|
||
predicates defined in the files.
|
||
|
||
YAP will search for @var{ObjectFiles} in the current directory first. If
|
||
it cannot find them it will search for the files using the environment
|
||
variable @code{YAPLIBDIR}, if defined, or in the default library.
|
||
|
||
In a.out systems YAP by default only reserves a fixed amount of memory
|
||
for object code (64 Kbytes in the current version). Should this size
|
||
prove inadequate the flag @code{-c n} can be passed to YAP (in the
|
||
command line invoking YAP) to force the allocation of @code{n} Kbytes.
|
||
|
||
@node Sav&Rest, Yap4 Notes, Loading Objects, C-Interface
|
||
@section Saving and Restoring
|
||
|
||
@comment The primitive predicates @code{save} and @code{restore} will save and restore
|
||
@comment object code loaded with @code{load_foreign_files}. However, the values of
|
||
@comment any non-static data created by the C files loaded will not be saved nor
|
||
@comment restored.
|
||
|
||
Yap4 currently does not support @code{save} and @code{restore} for object code
|
||
loaded with @code{load_foreign_files}. We plan to support save and restore
|
||
in future releases of Yap.
|
||
|
||
@node Yap4 Notes, , Sav&Rest, C-Interface
|
||
@section Changes to the C-Interface in Yap4
|
||
|
||
Yap4 includes several changes over the previous @code{load_foreign_files}
|
||
interface. These changes were required to support the new binary code
|
||
formats, such as ELF used in Solaris2 and Linux.
|
||
@itemize @bullet
|
||
@item All Names of YAP objects now start with @var{YAP_}. This is
|
||
designed to avoid clashes with other code. Use @code{YapInterface.h} to
|
||
take advantage of the new interface. @code{c_interface.h} is still
|
||
available if you cannot port the code to the new interface.
|
||
|
||
@item Access to elements in the new interface always goes through
|
||
@emph{functions}. This includes access to the argument registers,
|
||
@code{YAP_ARG1} to @code{YAP_ARG16}. This change breaks code such as
|
||
@code{unify(&ARG1,&t)}, which is nowadays:
|
||
@example
|
||
@{
|
||
YAP_Unify(ARG1, t);
|
||
@}
|
||
@end example
|
||
|
||
@item @code{cut_fail()} and @code{cut_succeed()} are now functions.
|
||
|
||
@item The use of @code{Deref} is deprecated. All functions that return
|
||
Prolog terms, including the ones that access arguments, already
|
||
dereferenciate their arguments.
|
||
|
||
@item Space allocated with PRESERVE_DATA is ignored by garbage
|
||
collection and stack shifting. As a result, any pointers to a Prolog
|
||
stack object, including some terms, may be corrupted after garbage
|
||
collection or stack shifting. Prolog terms should instead be stored as
|
||
arguments to the backtrackable procedure.
|
||
|
||
@end itemize
|
||
|
||
@node YapLibrary, Compatibility, C-Interface, Top
|
||
@chapter Using YAP as a Library
|
||
|
||
YAP can be used as a library to be called from other
|
||
programs. To do so, you must first create the YAP library:
|
||
@example
|
||
make library
|
||
make install_library
|
||
@end example
|
||
This will install a file @code{libyap.a} in @var{LIBDIR} and the Prolog
|
||
headers in @var{INCLUDEDIR}. The library contains all the functionality
|
||
available in YAP, except the foreign function loader and for
|
||
@code{Yap}'s startup routines.
|
||
|
||
To actually use this library you must follow a five step process:
|
||
|
||
@enumerate
|
||
@item
|
||
You must initialize the YAP environment. A single function,
|
||
@code{YAP_FastInit} asks for a contiguous chunk in your memory space, fills
|
||
it in with the data-base, and sets up YAP's stacks and
|
||
execution registers. You can use a saved space from a standard system by
|
||
calling @code{save_program/1}.
|
||
|
||
@item You then have to prepare a query to give to
|
||
YAP. A query is a Prolog term, and you just have to use the same
|
||
functions that are available in the C-interface.
|
||
|
||
@item You can then use @code{YAP_RunGoal(query)} to actually evaluate your
|
||
query. The argument is the query term @code{query}, and the result is 1
|
||
if the query succeeded, and 0 if it failed.
|
||
|
||
@item You can use the term destructor functions to check how
|
||
arguments were instantiated.
|
||
|
||
@item If you want extra solutions, you can use
|
||
@code{YAP_RestartGoal()} to obtain the next solution.
|
||
|
||
@end enumerate
|
||
|
||
The next program shows how to use this system. We assume the saved
|
||
program contains two facts for the procedure @t{b}:
|
||
|
||
@example
|
||
@cartouche
|
||
#include <stdio.h>
|
||
#include "Yap/YapInterface.h"
|
||
|
||
|
||
int
|
||
main(int argc, char *argv[]) @{
|
||
if (YAP_FastInit("saved_state") == YAP_BOOT_ERROR)
|
||
exit(1);
|
||
if (YAP_RunGoal(YAP_MkAtomTerm(YAP_LookupAtom("do")))) @{
|
||
printf("Success\n");
|
||
while (YAP_RestartGoal())
|
||
printf("Success\n");
|
||
@}
|
||
printf("NO\n");
|
||
@}
|
||
@end cartouche
|
||
@end example
|
||
|
||
The program first initializes YAP, calls the query for the
|
||
first time and succeeds, and then backtracks twice. The first time
|
||
backtracking succeeds, the second it fails and exits.
|
||
|
||
To compile this program it should be sufficient to do:
|
||
|
||
@example
|
||
cc -o exem -I../Yap4.3.0 test.c -lYap -lreadline -lm
|
||
@end example
|
||
|
||
You may need to adjust the libraries and library paths depending on the
|
||
Operating System and your installation of Yap.
|
||
|
||
Note that Yap4.3.0 provides the first version of the interface. The
|
||
interface may change and improve in the future.
|
||
|
||
The following C-functions are available from Yap:
|
||
|
||
@itemize @bullet
|
||
@item YAP_CompileClause(@code{YAP_Term} @var{Clause})
|
||
@findex YAP_CompileClause/1
|
||
Compile the Prolog term @var{Clause} and assert it as the last clause
|
||
for the corresponding procedure.
|
||
|
||
@item @code{int} YAP_ContinueGoal(@code{void})
|
||
@findex YAP_ContinueGoal/0
|
||
Continue execution from the point where it stopped.
|
||
|
||
@item @code{void} YAP_Error(@code{int} @var{ID},@code{YAP_Term} @var{Cause},@code{char *} @var{error_description})
|
||
@findex YAP_Error/1
|
||
Generate an YAP System Error with description given by the string
|
||
@var{error_description}. @var{ID} is the error ID, if known, or
|
||
@code{0}. @var{Cause} is the term that caused the crash.
|
||
|
||
@item @code{void} YAP_Exit(@code{int} @var{exit_code})
|
||
@findex YAP_Exit/1
|
||
Exit YAP immediately. The argument @var{exit_code} gives the error code
|
||
and is supposed to be 0 after successful execution in Unix and Unix-like
|
||
systems.
|
||
|
||
@item @code{YAP_Term} YAP_GetValue(@code{Atom} @var{at})
|
||
@findex YAP_GetValue/1
|
||
Return the term @var{value} associated with the atom @var{at}. If no
|
||
such term exists the function will return the empty list.
|
||
|
||
@item YAP_FastInit(@code{char *} @var{SavedState})
|
||
@findex YAP_FastInit/1
|
||
Initialize a copy of YAP from @var{SavedState}. The copy is
|
||
monolithic and currently must be loaded at the same address where it was
|
||
saved. @code{YAP_FastInit} is a simpler version of @code{YAP_Init}.
|
||
|
||
@item YAP_Init(@var{InitInfo})
|
||
@findex YAP_Init/1
|
||
Initialize YAP. The arguments are in a @code{C}
|
||
structure of type @code{YAP_init_args}.
|
||
|
||
The fields of @var{InitInfo} are @code{char *} @var{SavedState},
|
||
@code{int} @var{HeapSize}, @code{int} @var{StackSize}, @code{int}
|
||
@var{TrailSize}, @code{int} @var{NumberofWorkers}, @code{int}
|
||
@var{SchedulerLoop}, @code{int} @var{DelayedReleaseLoad}, @code{int}
|
||
@var{argc}, @code{char **} @var{argv}, @code{int} @var{ErrorNo}, and
|
||
@code{char *} @var{ErrorCause}. The function returns an integer, which
|
||
indicates the current status. If the result is @code{YAP_BOOT_ERROR}
|
||
booting failed.
|
||
|
||
If @var{SavedState} is not NULL, try to open and restore the file
|
||
@var{SavedState}. Initially YAP will search in the current directory. If
|
||
the saved state does not exist in the current directory YAP will use
|
||
either the default library directory or the directory given by the
|
||
environment variable @code{YAPLIBDIR}. Note that currently
|
||
the saved state must be loaded at the same address where it was saved.
|
||
|
||
If @var{HeapSize} is different from 0 use @var{HeapSize} as the minimum
|
||
size of the Heap (or code space). If @var{StackSize} is different from 0
|
||
use @var{HeapSize} as the minimum size for the Stacks. If
|
||
@var{TrailSize} is different from 0 use @var{TrailSize} as the minimum
|
||
size for the Trails.
|
||
|
||
The @var{NumberofWorkers}, @var{NumberofWorkers}, and
|
||
@var{DelayedReleaseLoad} are only of interest to the or-parallel system.
|
||
|
||
The argument count @var{argc} and string of arguments @var{argv}
|
||
arguments are to be passed to user programs as the arguments used to
|
||
call YAP.
|
||
|
||
If booting failed you may consult @code{ErrorNo} and @code{ErrorCause}
|
||
for the cause of the error, or call
|
||
@code{YAP_Error(ErrorNo,0L,ErrorCause)} to do default processing.
|
||
|
||
|
||
@item @code{void} YAP_PutValue(@code{Atom} @var{at}, @code{YAP_Term} @var{value})
|
||
@findex YAP_PutValue/2
|
||
Associate the term @var{value} with the atom @var{at}. The term
|
||
@var{value} must be a constant. This functionality is used by YAP as a
|
||
simple way for controlling and communicating with the Prolog run-time.
|
||
|
||
@item @code{YAP_Term} YAP_Read(@code{int (*)(void)} @var{GetC})
|
||
@findex YAP_Read/1
|
||
Parse a Term using the function @var{GetC} to input characters.
|
||
|
||
@item @code{YAP_Term} YAP_RunGoal(@code{YAP_Term} @var{Goal})
|
||
@findex YAP_RunGoal/1
|
||
Execute query @var{Goal} and return 1 if the query succeeds, and
|
||
0 otherwise. The predicate returns 0 if failure, otherwise it will
|
||
return @var{YAP_Term}. Note that @var{YAP_Term} may change due to garbage
|
||
collection, so you should use something like:
|
||
@example
|
||
t = YAP_RunGoal(t);
|
||
if (t == 0) return FALSE;
|
||
@end example
|
||
If the execution fails, garbage collection might still have changed
|
||
the term, so you should not use the input argument again.
|
||
|
||
An alternative is to use @emph{slots}, as shown next:
|
||
|
||
@example
|
||
long sl = YAP_InitSlot(scoreTerm);
|
||
|
||
out = YAP_RunGoal(t);
|
||
t = YAP_GetFromSlot(sl);
|
||
YAP_RecoverSlots(1);
|
||
if (out == 0) return FALSE;
|
||
@end example
|
||
Slots are safe houses in the stack, preserved by the garbage collector
|
||
and the stack shifter. In this case, we use a slot to preserve @var{t}
|
||
during the execution of @code{YAP_RunGoal}. When the execution of
|
||
@var{t} is over we read the (possibly changed) value of @var{t} back
|
||
from the slot @var{sl} and tell YAP that the slot @var{sl} is not
|
||
needed and can be given back to the system.
|
||
|
||
@item @code{int} YAP_RestartGoal(@code{void})
|
||
@findex YAP_RestartGoal/0
|
||
Look for the next solution to the current query by forcing YAP to backtrack.
|
||
|
||
@item @code{int} YAP_Reset(@code{void})
|
||
@findex YAP_Reset/0
|
||
Reset execution environment (similar to the @code{abort/0}
|
||
built-in). This is useful when you want to start a new query before
|
||
asking all solutions to the previous query.
|
||
|
||
@item @code{YAP_Bool} YAP_GoalHasException(@code{YAP_Term *tp})
|
||
@findex YAP_RestartGoal/1
|
||
Check if the last goal generated an exception, and if so copy it to the
|
||
space pointed to by @var{tp}
|
||
|
||
@item @code{void} YAP_ClearExceptions(@code{void})
|
||
@findex YAP_ClearExceptions/0
|
||
Reset any exceptions left over by the system.
|
||
|
||
@item @code{void} YAP_Write(@code{YAP_Term} @var{t}, @code{void (*)(int)}
|
||
@var{PutC}, @code{int} @var{flags})
|
||
@findex YAP_Write/3
|
||
Write a Term @var{t} using the function @var{PutC} to output
|
||
characters. The term is written according to a mask of the following
|
||
flags in the @code{flag} argument: @code{YAP_WRITE_QUOTED},
|
||
@code{YAP_WRITE_HANDLE_VARS}, and @code{YAP_WRITE_IGNORE_OPS}.
|
||
|
||
@item @code{void} YAP_WriteBuffer(@code{YAP_Term} @var{t}, @code{char *}
|
||
@var{buff}, @code{unsigned int}
|
||
@var{size}, @code{int} @var{flags})
|
||
@findex YAP_WriteBuffer/4
|
||
Write a YAP_Term @var{t} to buffer @var{buff} with size @var{size}. The
|
||
term is written according to a mask of the following flags in the
|
||
@code{flag} argument: @code{YAP_WRITE_QUOTED},
|
||
@code{YAP_WRITE_HANDLE_VARS}, and @code{YAP_WRITE_IGNORE_OPS}.
|
||
|
||
@item @code{void} YAP_InitConsult(@code{int} @var{mode}, @code{char *} @var{filename})
|
||
@findex YAP_InitConsult/2
|
||
Enter consult mode on file @var{filename}. This mode maintains a few
|
||
data-structures internally, for instance to know whether a predicate
|
||
before or not. It is still possible to execute goals in consult mode.
|
||
|
||
If @var{mode} is @code{TRUE} the file will be reconsulted, otherwise
|
||
just consulted. In practice, this function is most useful for
|
||
bootstrapping Prolog, as otherwise one may call the Prolog predicate
|
||
@code{compile/1} or @code{consult/1} to do compilation.
|
||
|
||
Note that it is up to the user to open the file @var{filename}. The
|
||
@code{YAP_InitConsult} function only uses the file name for internal
|
||
bookkeeping.
|
||
|
||
@item @code{void} YAP_EndConsult(@code{void})
|
||
@findex YAP_EndConsult/0
|
||
Finish consult mode.
|
||
|
||
@end itemize
|
||
|
||
Some observations:
|
||
|
||
@itemize @bullet
|
||
@item The system will core dump if you try to load the saved state in a
|
||
different address from where it was made. This may be a problem if
|
||
your program uses @code{mmap}. This problem will be addressed in future
|
||
versions of YAP.
|
||
|
||
@item Currently, the YAP library will pollute the name
|
||
space for your program.
|
||
|
||
@item The initial library includes the complete YAP system. In
|
||
the future we plan to split this library into several smaller libraries
|
||
(e.g. if you do not want to perform I/O).
|
||
|
||
@item You can generate your own saved states. Look at the
|
||
@code{boot.yap} and @code{init.yap} files.
|
||
|
||
@end itemize
|
||
|
||
@node Compatibility, Operators, YapLibrary, Top
|
||
@chapter Compatibility with Other Prolog systems
|
||
|
||
YAP has been designed to be as compatible as possible with
|
||
other Prolog systems, and initially with C-Prolog. More recent work on
|
||
YAP has included features initially proposed for the Quintus
|
||
and SICStus Prolog systems.
|
||
|
||
Developments since @code{Yap4.1.6} we have striven at making
|
||
YAP compatible with the ISO-Prolog standard.
|
||
|
||
@menu
|
||
* C-Prolog:: Compatibility with the C-Prolog interpreter
|
||
* SICStus Prolog:: Compatibility with the SICStus Prolog system
|
||
* ISO Prolog:: Compatibility with the ISO Prolog standard
|
||
@end menu
|
||
|
||
@node C-Prolog, SICStus Prolog, , Compatibility
|
||
@section Compatibility with the C-Prolog interpreter
|
||
|
||
@menu
|
||
C-Prolog Compatibility
|
||
* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog
|
||
* Fully C-Prolog Compatible:: Yap predicates fully compatible with
|
||
C-Prolog
|
||
* Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog
|
||
* Not in C-Prolog:: Yap predicates not available in C-Prolog
|
||
* Not in YAP:: C-Prolog predicates not available in YAP
|
||
@end menu
|
||
|
||
@node Major Differences with C-Prolog, Fully C-Prolog Compatible, , C-Prolog
|
||
@subsection Major Differences between YAP and C-Prolog.
|
||
|
||
YAP includes several extensions over the original C-Prolog system. Even
|
||
so, most C-Prolog programs should run under YAP without changes.
|
||
|
||
The most important difference between YAP and C-Prolog is that, being
|
||
YAP a compiler, some changes should be made if predicates such as
|
||
@code{assert}, @code{clause} and @code{retract} are used. First
|
||
predicates which will change during execution should be declared as
|
||
@code{dynamic} by using commands like:
|
||
|
||
@example
|
||
:- dynamic f/n.
|
||
@end example
|
||
|
||
@noindent where @code{f} is the predicate name and n is the arity of the
|
||
predicate. Note that several such predicates can be declared in a
|
||
single command:
|
||
@example
|
||
:- dynamic f/2, ..., g/1.
|
||
@end example
|
||
|
||
Primitive predicates such as @code{retract} apply only to dynamic
|
||
predicates. Finally note that not all the C-Prolog primitive predicates
|
||
are implemented in YAP. They can easily be detected using the
|
||
@code{unknown} system predicate provided by YAP.
|
||
|
||
Last, by default YAP enables character escapes in strings. You can
|
||
disable the special interpretation for the escape character by using:
|
||
@example
|
||
@code{:- yap_flag(character_escapes,off).}
|
||
@end example
|
||
@noindent
|
||
or by using:
|
||
@example
|
||
@code{:- yap_flag(language,cprolog).}
|
||
@end example
|
||
|
||
@node Fully C-Prolog Compatible, Not Strictly C-Prolog Compatible, Major Differences with C-Prolog, C-Prolog
|
||
@subsection Yap predicates fully compatible with C-Prolog
|
||
|
||
These are the Prolog built-ins that are fully compatible in both
|
||
C-Prolog and YAP:
|
||
|
||
@printindex cy
|
||
|
||
@node Not Strictly C-Prolog Compatible, Not in C-Prolog, Fully C-Prolog Compatible, C-Prolog
|
||
@subsection Yap predicates not strictly compatible with C-Prolog
|
||
|
||
These are YAP built-ins that are also available in C-Prolog, but
|
||
that are not fully compatible:
|
||
|
||
@printindex ca
|
||
|
||
@node Not in C-Prolog, Not in YAP, Not Strictly C-Prolog Compatible, C-Prolog
|
||
@subsection Yap predicates not available in C-Prolog
|
||
|
||
These are YAP built-ins not available in C-Prolog.
|
||
|
||
@printindex cn
|
||
|
||
@node Not in YAP, , Not in C-Prolog, C-Prolog
|
||
@subsection Yap predicates not available in C-Prolog
|
||
|
||
These are C-Prolog built-ins not available in YAP:
|
||
|
||
@table @code
|
||
@item 'LC'
|
||
The following Prolog text uses lower case letters.
|
||
|
||
@item 'NOLC'
|
||
The following Prolog text uses upper case letters only.
|
||
@end table
|
||
|
||
@node SICStus Prolog, ISO Prolog, C-Prolog, Compatibility
|
||
@section Compatibility with the Quintus and SICStus Prolog systems
|
||
|
||
The Quintus Prolog system was the first Prolog compiler to use Warren's
|
||
Abstract Machine. This system was very influential in the Prolog
|
||
community. Quintus Prolog implemented compilation into an abstract
|
||
machine code, which was then emulated. Quintus Prolog also included
|
||
several new built-ins, an extensive library, and in later releases a
|
||
garbage collector. The SICStus Prolog system, developed at SICS (Swedish
|
||
Institute of Computer Science), is an emulator based Prolog system
|
||
largely compatible with Quintus Prolog. SICStus Prolog has evolved
|
||
through several versions. The current version includes several
|
||
extensions, such as an object implementation, co-routining, and
|
||
constraints.
|
||
|
||
Recent work in YAP has been influenced by work in Quintus and
|
||
SICStus Prolog. Wherever possible, we have tried to make YAP
|
||
compatible with recent versions of these systems, and specifically of
|
||
SICStus Prolog. You should use
|
||
@example
|
||
:- yap_flag(language, sicstus).
|
||
@end example
|
||
@noindent
|
||
for maximum compatibility with SICStus Prolog.
|
||
|
||
@menu
|
||
SICStus Compatibility
|
||
* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog
|
||
* Fully SICStus Compatible:: Yap predicates fully compatible with
|
||
SICStus Prolog
|
||
* Not Strictly SICStus Compatible:: Yap predicates not strictly as
|
||
SICStus Prolog
|
||
* Not in SICstus Prolog:: Yap predicates not available in SICStus Prolog
|
||
@end menu
|
||
|
||
@node Major Differences with SICStus, Fully SICStus Compatible, , SICStus Prolog
|
||
@subsection Major Differences between YAP and SICStus Prolog.
|
||
|
||
Both YAP and SICStus Prolog obey the Edinburgh Syntax and are based on
|
||
the WAM. Even so, there are quite a few important differences:
|
||
|
||
@itemize @bullet
|
||
@item Differently from SICStus Prolog, YAP does not have a
|
||
notion of interpreted code. All code in YAP is compiled.
|
||
|
||
@item YAP does not support an intermediate byte-code
|
||
representation, so the @code{fcompile/1} and @code{load/1} built-ins are
|
||
not available in YAP.
|
||
|
||
@item YAP implements escape sequences as in the ISO standard. SICStus
|
||
Prolog implements Unix-like escape sequences.
|
||
|
||
@item YAP implements @code{initialization/1} as per the ISO
|
||
standard. Use @code{prolog_initialization/1} for the SICStus Prolog
|
||
compatible built-in.
|
||
|
||
@item Prolog flags are different in SICStus Prolog and in YAP.
|
||
|
||
@item The SICStus Prolog @code{on_exception/3} and
|
||
@code{raise_exception} built-ins correspond to the ISO built-ins
|
||
@code{catch/3} and @code{throw/1}.
|
||
|
||
@item The following SICStus Prolog v3 built-ins are not (currently)
|
||
implemented in YAP (note that this is only a partial list):
|
||
@code{call_cleanup/1}, @code{file_search_path/2},
|
||
@code{stream_interrupt/3}, @code{reinitialize/0}, @code{help/0},
|
||
@code{help/1}, @code{trimcore/0}, @code{load_files/1},
|
||
@code{load_files/2}, and @code{require/1}.
|
||
|
||
The previous list is incomplete. We also cannot guarantee full
|
||
compatibility for other built-ins (although we will try to address any
|
||
such incompatibilities). Last, SICStus Prolog is an evolving system, so
|
||
one can be expect new incompatibilities to be introduced in future
|
||
releases of SICStus Prolog.
|
||
|
||
@item YAP allows asserting and abolishing static code during
|
||
execution through the @code{assert_static/1} and @code{abolish/1}
|
||
built-ins. This is not allowed in Quintus Prolog or SICStus Prolog.
|
||
|
||
@item YAP implements rational trees and co-routining but they
|
||
are not included by default in the system. You must enable these
|
||
extensions when compiling the system.
|
||
|
||
@item YAP does not currently implement constraints.
|
||
|
||
@item The socket predicates, although designed to be compatible with
|
||
SICStus Prolog, are built-ins, not library predicates, in YAP.
|
||
|
||
@item This list is incomplete.
|
||
|
||
@end itemize
|
||
|
||
The following differences only exist if the @code{language} flag is set
|
||
to @code{yap} (the default):
|
||
|
||
@itemize @bullet
|
||
@item The @code{consult/1} predicate in YAP follows C-Prolog
|
||
semantics. That is, it adds clauses to the data base, even for
|
||
preexisting procedures. This is different from @code{consult/1} in
|
||
SICStus Prolog.
|
||
|
||
@cindex update semantics
|
||
@item By default, the data-base in YAP follows "immediate update
|
||
semantics", instead of "logical update semantics", as Quintus Prolog or
|
||
SICStus Prolog do. The difference is depicted in the next example:
|
||
|
||
@example
|
||
:- dynamic a/1.
|
||
|
||
?- assert(a(1)).
|
||
|
||
?- retract(a(X)), X1 is X +1, assertz(a(X)).
|
||
@end example
|
||
With immediate semantics, new clauses or entries to the data base are
|
||
visible in backtracking. In this example, the first call to
|
||
@code{retract/1} will succeed. The call to @strong{assertz/1} will then
|
||
succeed. On backtracking, the system will retry
|
||
@code{retract/1}. Because the newly asserted goal is visible to
|
||
@code{retract/1}, it can be retracted from the data base, and
|
||
@code{retract(a(X))} will succeed again. The process will continue
|
||
generating integers for ever. Immediate semantics were used in C-Prolog.
|
||
|
||
With logical update semantics, any additions or deletions of clauses
|
||
for a goal @emph{will not affect previous activations of the
|
||
goal}. In the example, the call to @code{assertz/1} will not see the
|
||
update performed by the @code{assertz/1}, and the query will have a
|
||
single solution.
|
||
|
||
Calling @code{yap_flag(update_semantics,logical)} will switch
|
||
YAP to use logical update semantics.
|
||
|
||
@item @code{dynamic/1} is a built-in, not a directive, in YAP.
|
||
|
||
@item By default, YAP fails on undefined predicates. To follow default
|
||
SICStus Prolog use:
|
||
@example
|
||
:- yap_flag(unknown,error).
|
||
@end example
|
||
|
||
@item By default, directives in YAP can be called from the top level.
|
||
|
||
@end itemize
|
||
|
||
@node Fully SICStus Compatible, Not Strictly SICStus Compatible, Major Differences with SICStus, SICStus Prolog
|
||
@subsection Yap predicates fully compatible with SICStus Prolog
|
||
|
||
These are the Prolog built-ins that are fully compatible in both SICStus
|
||
Prolog and YAP:
|
||
|
||
@printindex sy
|
||
|
||
@node Not Strictly SICStus Compatible, Not in SICstus Prolog, Fully SICStus Compatible, SICStus Prolog
|
||
@subsection Yap predicates not strictly compatible with SICStus Prolog
|
||
|
||
These are YAP built-ins that are also available in SICStus Prolog, but
|
||
that are not fully compatible:
|
||
|
||
@printindex sa
|
||
|
||
@node Not in SICstus Prolog, , Not Strictly SICStus Compatible, SICStus Prolog
|
||
@subsection Yap predicates not available in SICStus Prolog
|
||
|
||
These are YAP built-ins not available in SICStus Prolog.
|
||
|
||
@printindex sn
|
||
|
||
|
||
@node ISO Prolog, , SICStus Prolog, Compatibility
|
||
@section Compatibility with the ISO Prolog standard
|
||
|
||
The Prolog standard was developed by ISO/IEC JTC1/SC22/WG17, the
|
||
international standardization working group for the programming language
|
||
Prolog. The book "Prolog: The Standard" by Deransart, Ed-Dbali and
|
||
Cervoni gives a complete description of this standard. Development in
|
||
YAP from YAP4.1.6 onwards have striven at making YAP
|
||
compatible with ISO Prolog. As such:
|
||
|
||
@itemize @bullet
|
||
@item YAP now supports all of the built-ins required by the
|
||
ISO-standard, and,
|
||
@item Error-handling is as required by the standard.
|
||
@end itemize
|
||
|
||
YAP by default is not fully ISO standard compliant. You can set the
|
||
@code{language} flag to @code{iso} to obtain very good
|
||
compatibility. Setting this flag changes the following:
|
||
|
||
@itemize @bullet
|
||
@item By default, YAP uses "immediate update semantics" for its
|
||
database, and not "logical update semantics", as per the standard,
|
||
(@pxref{SICStus Prolog}). This affects @code{assert/1},
|
||
@code{retract/1}, and friends.
|
||
|
||
Calling @code{set_prolog_flag(update_semantics,logical)} will switch
|
||
YAP to use logical update semantics.
|
||
|
||
@item By default, YAP implements the @code{atom_chars/2}
|
||
(@pxref{Testing Terms}), and @code{number_chars/2}, (@pxref{Testing
|
||
Terms}), built-ins as per the original Quintus Prolog definition, and
|
||
not as per the ISO definition.
|
||
|
||
Calling @code{set_prolog_flag(to_chars_mode,iso)} will switch
|
||
YAP to use the ISO definition for
|
||
@code{atom_chars/2} and @code{number_chars/2}.
|
||
|
||
@item By default, YAP fails on undefined predicates. To follow the ISO
|
||
Prolog standard use:
|
||
@example
|
||
:- set_prolog_flag(unknown,error).
|
||
@end example
|
||
|
||
@item By default, YAP allows executable goals in directives. In ISO mode
|
||
most directives can only be called from top level (the exceptions are
|
||
@code{set_prolog_flag/2} and @code{op/3}).
|
||
|
||
@item Error checking for meta-calls under ISO Prolog mode is stricter
|
||
than by default.
|
||
|
||
@item The @code{strict_iso} flag automatically enables the ISO Prolog
|
||
standard. This feature should disable all features not present in the
|
||
standard.
|
||
|
||
@end itemize
|
||
|
||
The following incompatibilities between YAP and the ISO standard are
|
||
known to still exist:
|
||
|
||
@itemize @bullet
|
||
|
||
@item Currently, YAP does not handle overflow errors in integer
|
||
operations, and handles floating-point errors only in some
|
||
architectures. Otherwise, YAP follows IEEE arithmetic.
|
||
|
||
@end itemize
|
||
|
||
Please inform the authors on other incompatibilities that may still
|
||
exist.
|
||
|
||
@node Operators, Predicate Index, Compatibility, Top
|
||
@appendix Summary of Yap Predefined Operators
|
||
|
||
|
||
The Prolog syntax caters for operators of three main kinds:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
prefix;
|
||
@item
|
||
infix;
|
||
@item
|
||
postfix.
|
||
@end itemize
|
||
|
||
Each operator has precedence in the range 1 to 1200, and this
|
||
precedence is used to disambiguate expressions where the structure of the
|
||
term denoted is not made explicit using brackets. The operator of higher
|
||
precedence is the main functor.
|
||
|
||
If there are two operators with the highest precedence, the ambiguity
|
||
is solved analyzing the types of the operators. The possible infix types are:
|
||
xfx, xfy, yfx.
|
||
|
||
With an operator of type xfx both sub-expressions must have lower
|
||
precedence than the operator itself, unless they are bracketed (which
|
||
assigns to them zero precedence). With an operator type xfy only the
|
||
left-hand sub-expression must have lower precedence. The opposite happens
|
||
for yfx type.
|
||
|
||
A prefix operator can be of type fx or fy, and a postfix operator, xf, yf.
|
||
The meaning of the notation is analogous to the above.
|
||
@example
|
||
a + b * c
|
||
@end example
|
||
@noindent
|
||
means
|
||
@example
|
||
a + (b * c)
|
||
@end example
|
||
@noindent
|
||
as + and * have the following types and precedences:
|
||
@example
|
||
:-op(500,yfx,'+').
|
||
:-op(400,yfx,'*').
|
||
@end example
|
||
|
||
Now defining
|
||
@example
|
||
:-op(700,xfy,'++').
|
||
:-op(700,xfx,'=:=').
|
||
a ++ b =:= c
|
||
@end example
|
||
@noindent means
|
||
@example
|
||
a ++ (b =:= c)
|
||
@end example
|
||
|
||
|
||
The following is the list of the declarations of the predefined operators:
|
||
|
||
@example
|
||
:-op(1200,fx,['?-', ':-']).
|
||
:-op(1200,xfx,[':-','-->']).
|
||
:-op(1150,fx,[block,dynamic,mode,public,multifile,meta_predicate,
|
||
sequential,table,initialization]).
|
||
:-op(1100,xfy,[';','|']).
|
||
:-op(1050,xfy,->).
|
||
:-op(1000,xfy,',').
|
||
:-op(999,xfy,'.').
|
||
:-op(900,fy,['\+', not]).
|
||
:-op(900,fx,[nospy, spy]).
|
||
:-op(700,xfx,[@@>=,@@=<,@@<,@@>,<,=,>,=:=,=\=,\==,>=,=<,==,\=,=..,is]).
|
||
:-op(500,yfx,['\/','/\','+','-']).
|
||
:-op(500,fx,['+','-']).
|
||
:-op(400,yfx,['<<','>>','//','*','/']).
|
||
:-op(300,xfx,mod).
|
||
:-op(200,xfy,['^','**']).
|
||
:-op(50,xfx,same).
|
||
@end example
|
||
|
||
@node Predicate Index, Concept Index, Operators, Top
|
||
@unnumbered Predicate Index
|
||
@printindex fn
|
||
|
||
@node Concept Index, , Predicate Index, Top
|
||
@unnumbered Concept Index
|
||
@printindex cp
|
||
|
||
@contents
|
||
|
||
@bye
|