SWI-Prolog-7 4 1
SWI-Prolog-7 4 1
Reference Manual
Updated for version 7.4-1, March 2017
Jan Wielemaker
[email protected]
http://www.swi-prolog.org
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
License. To view a copy of this license, visit http://creativecommons.org/
licenses/by-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street,
Suite 900, Mountain View, California, 94041, USA.
Contents
1 Introduction 11
1.1 Positioning SWI-Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2 Status and releases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3 Should I be using SWI-Prolog? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Support the SWI-Prolog project . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5 Implementation history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2 Overview 16
2.1 Getting started quickly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.1.1 Starting SWI-Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.1.2 Executing a query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2 The users initialisation file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 Initialisation files and goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4 Command line options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.1 Informational command line options . . . . . . . . . . . . . . . . . . . . . . 19
2.4.2 Command line options for running Prolog . . . . . . . . . . . . . . . . . . . 19
2.4.3 Controlling the stack sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.4.4 Running goals from the command line . . . . . . . . . . . . . . . . . . . . . 22
2.4.5 Compilation options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.4.6 Maintenance options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5 GNU Emacs Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.6 Online Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.7 Command line history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.8 Reuse of top-level bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.9 Overview of the Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.10 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.10.1 During program development . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.10.2 For running the result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.11 Environment Control (Prolog flags) . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.12 An overview of hook predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.13 Automatic loading of libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.14 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.15 The SWI-Prolog syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.15.1 ISO Syntax Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.16 Rational trees (cyclic terms) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.17 Just-in-time clause indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.17.1 Future directions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.17.2 Indexing and portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.18 Wide character support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4 Built-in Predicates 78
4.1 Notation of Predicate Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.2 Character representation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.3 Loading Prolog source files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.3.1 Conditional compilation and program transformation . . . . . . . . . . . . . 90
4.3.2 Reloading files, active code and threads . . . . . . . . . . . . . . . . . . . . 94
4.3.3 Quick load files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
4.4 Editor Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.4.1 Customizing the editor interface . . . . . . . . . . . . . . . . . . . . . . . . 98
4.5 List the program, predicates or clauses . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.6 Verify Type of a Term . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.7 Comparison and Unification of Terms . . . . . . . . . . . . . . . . . . . . . . . . . 102
4.7.1 Standard Order of Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
4.7.2 Special unification and comparison predicates . . . . . . . . . . . . . . . . . 103
4.8 Control Predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.9 Meta-Call Predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.10 Delimited continuations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6 Modules 251
6.1 Why Use Modules? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
6.2 Defining a Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
6.3 Importing Predicates into a Module . . . . . . . . . . . . . . . . . . . . . . . . . . 252
6.4 Defining a meta-predicate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
6.5 Overruling Module Boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
6.5.1 Explicit manipulation of the calling context . . . . . . . . . . . . . . . . . . 256
6.6 Interacting with modules from the top level . . . . . . . . . . . . . . . . . . . . . . 257
6.7 Composing modules from other modules . . . . . . . . . . . . . . . . . . . . . . . . 257
6.8 Operators and modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
6.9 Dynamic importing using import modules . . . . . . . . . . . . . . . . . . . . . . . 258
6.10 Reserved Modules and using the user module . . . . . . . . . . . . . . . . . . . . 259
6.11 An alternative import/export interface . . . . . . . . . . . . . . . . . . . . . . . . . 259
6.12 Dynamic Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
6.13 Transparent predicates: definition and context module . . . . . . . . . . . . . . . . . 260
6.14 Module properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
6.15 Compatibility of the Module System . . . . . . . . . . . . . . . . . . . . . . . . . . 263
F Summary 525
F.1 Predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
F.2 Library predicates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
F.2.1 library(aggregate) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
F.2.2 library(apply) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
F.2.3 library(assoc) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
F.2.4 library(broadcast) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
F.2.5 library(charsio) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
F.2.6 library(check) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
F.2.7 library(clpb) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
F.2.8 library(clpfd) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
F.2.9 library(clpqr) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
F.2.10 library(csv) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
F.2.11 library(debug) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
F.2.12 library(error) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
F.2.13 library(iostream) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
F.2.14 library(summaries.d/iostream/tex) . . . . . . . . . . . . . . . . . . . . . . . 545
F.2.15 library(lists) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
F.2.16 library(option) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
F.2.17 library(optparse) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
F.2.18 library(ordsets) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
F.2.19 library(persistency) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
F.2.20 library(predicate options) . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
F.2.21 library(prologpack) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
F.2.22 library(prologxref) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
F.2.23 library(pairs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
F.2.24 library(pio) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
F.2.25 library(random) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
F.2.26 library(readutil) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
F.2.27 library(record) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
F.2.28 library(registry) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
F.2.29 library(simplex) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
F.2.30 library(ugraphs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
F.2.31 library(url) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
F.2.32 library(www browser) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
F.2.33 library(solution sequences) . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
F.2.34 library(thread pool) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
F.2.35 library(varnumbers) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
F.2.36 library(yall) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
F.3 Arithmetic Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
F.4 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
On the other hand, SWI-Prolog offers some facilities that are widely appreciated by users:
Nice environment
SWI-Prolog provides a good command line environment, including Do What I Mean, auto-
completion, history and a tracer that operates on single key strokes. The system automatically
recompiles modified parts of the source code using the make/0 command. The system can
be instructed to open an arbitrary editor on the right file and line based on its source database.
It ships with various graphical tools and can be combined with the SWI-Prolog editor, PDT
(Eclipse plugin for Prolog) or GNU-Emacs.
Fast compiler
Even very large applications can be loaded in seconds on most machines. If this is not enough,
there is the Quick Load Format. See qcompile/1 and qsave program/2.
Profiling
SWI-Prolog offers an execution profiler with either textual output or graphical output. Finding
and improving hotspots in a Prolog program may result in huge speedups.
Flexibility
SWI-Prolog can easily be integrated with C, supporting non-determinism in Prolog calling C
as well as C calling Prolog (see section 11). It can also be embedded in external programs (see
section 11.5). System predicates can be redefined locally to provide compatibility with other
Prolog systems.
Threads
Robust support for multiple threads may improve performance and is a key enabling factor for
deploying Prolog in server applications.
Interfaces
SWI-Prolog ships with many extension packages that provide robust interfaces to processes,
encryption, TCP/IP, TIPC, ODBC, SGML/XML/HTML, RDF, HTTP, graphics and much more.
1.6 Acknowledgements
Some small parts of the Prolog code of SWI-Prolog are modified versions of the corresponding Edin-
burgh C-Prolog code: grammar rule compilation and writef/2. Also some of the C-code originates
from C-Prolog: finding the path of the currently running executable and some of the code underlying
absolute file name/2. Ideas on programming style and techniques originate from C-Prolog
and Richard OKeefes thief editor. An important source of inspiration are the programming tech-
niques introduced by Anjo Anjewierden in PCE version 1 and 2.
Our special thanks go to those who had the fate of using the early versions of this system, sug-
gested extensions or reported bugs. Among them are Anjo Anjewierden, Huub Knops, Bob Wielinga,
Wouter Jansweijer, Luc Peerdeman, Eric Nombden, Frank van Harmelen, Bert Rengel.
Martin Jansche ([email protected]) has been so kind to reor-
ganise the sources for version 2.1.3 of this manual. Horst von Brand has been so kind to fix many
typos in the 2.7.14 manual. Thanks! Randy Sharp fixed many issues in the 6.0.x version of the manual.
Bart Demoen and Tom Schrijvers have helped me adding coroutining, constraints, global variables
and support for cyclic terms to the kernel. Tom Schrijvers has provided a first clp(fd) constraint solver,
the CHR compiler and some of the coroutining predicates. Markus Triska contributed the current
clp(fd) implementation.
Paul Singleton has integrated Fred Dushins Java-calls-Prolog side with his Prolog-calls-Java side
into the current bidirectional JPL interface package.
Richard OKeefe is gratefully acknowledged for his efforts to educate beginners as well as valu-
able comments on proposed new developments.
Scientific Software and Systems Limited, www.sss.co.nz has sponsored the development of
the SSL library, unbounded integer and rational number arithmetic and many enhancements to the
memory management of the system.
Leslie de Koninck has made clp(QR) available to SWI-Prolog.
Jeff Rosenwald contributed the TIPC networking library and Googles protocol buffer handling.
Paulo Mouras great experience in maintaining Logtalk for many Prolog systems including SWI-
Prolog has helped in many places fixing compatibility issues. He also worked on the MacOS port and
fixed many typos in the 5.6.9 release of the documentation.
machine% swipl
Welcome to SWI-Prolog ...
...
1 ?-
After starting Prolog, one normally loads a program into it using consult/1, which may be abbre-
viated by putting the name of the program file between square brackets. The following goal loads the
file likes.pl containing clauses for the predicates likes/2:
?- [likes].
% likes compiled, 0.00 sec, 17 clauses
true.
?-
After this point, Unix and Windows users unite, so if you are using Unix please continue at sec-
tion 2.1.2.
A folder (called directory in the remainder of this document) called swipl containing the
executables, libraries, etc., of the system. No files are installed outside this directory.
A program swipl-win.exe, providing a window for interaction with Prolog. The program
swipl.exe is a version of SWI-Prolog that runs in a console window.
The file extension .pl is associated with the program swipl-win.exe. Opening a .pl
file will cause swipl-win.exe to start, change directory to the directory in which the file to
open resides, and load this file.
The normal way to start the likes.pl file mentioned in section 2.1.1 is by simply double-
clicking this file in the Windows explorer.
?- likes(sam, X).
X = dahl ;
X = tandoori ;
...
X = chips.
?-
Note that the answer written by Prolog is a valid Prolog program that, when executed, produces the
same set of answers as the original program.2
Unix Windows
home happdatai/SWI-Prolog
After the first startup file is found it is loaded and Prolog stops looking for further startup files. The
name of the startup file can be changed with the -f file option. If File denotes an absolute path,
1
On most installations, single-character commands are executed without waiting for the RETURN key.
2
The SWI-Prolog top level differs in several ways from traditional Prolog top level. The current top level was designed
in cooperation with Ulrich Neumerkel.
3
Older versions first searched in the current working directory. This feature has been removed for security reasons.
Users can implement loading a setup file from the working directory in their global preference file.
this file is loaded, otherwise the file is searched for using the same conventions as for the default
startup file. Finally, if file is none, no file is loaded.
The installation provides a file customize/dotswiplrc with (commented) commands that
are often used to customize the behaviour of Prolog, such as interfacing to the editor, color selection
or history parameters. Many of the development tools provide menu entries for editing the startup file
and starting a fresh startup file from the system skeleton.
See also the -s (script) and -F (system-wide initialisation) in section 2.4 and section 2.3.
It tells SWI-Prolog to load load.pl, start the application using the entry point go/0 and instead
of entering the interactive top level exit after completing go/0.
The command line may have multiple -g goal occurrences. The goals are executed in order.
Possible choice points of individual goals are pruned. If a goal fails execution stops with exit status
1. If a goal raises an exception, the exception is printed and the process stops with exit code 2.
The -q may be used to suppress all informational messages as well as the error message that is
normally printed if an initialisation goal fails.
In MS-Windows, the same can be achieved using a short-cut with appropriately defined command
line arguments. A typically seen alternative is to write a file run.pl with content as illustrated below.
Double-clicking run.pl will start the application.
Section 2.10.2 discusses further scripting options, and chapter 12 discusses the generation of runtime
executables. Runtime executables are a means to deliver executables that do not require the Prolog
system.
--dump-runtime-variables [=format]
When given as the only option, it prints a sequence of variable settings that can be used in
shell scripts to deal with Prolog parameters. This feature is also used by swipl-ld (see
section 11.5). Below is a typical example of using this feature.
The option can be followed by =sh to dump in POSIX shell format (default) or =cmd to dump
in MS-Windows cmd.exe compatible format.
--help
When given as the only option, it summarises the most important options. Also available as -h
and -help.
--version
When given as the only option, it summarises the version and the architecture identifier. Also
available as -v.
--quiet
Set the Prolog flag verbose to silent, suppressing informational and banner messages.
Also available as -q.
--nodebug
Disable debugging. See the current prolog flag/2 flag generate debug info for
details.
--nosignals
Inhibit any signal handling by Prolog, a property that is sometimes desirable for embedded
applications. This option sets the flag signals to false. See section 11.4.21 for details.
--pldoc [=port]
Start the PlDoc documentation system on a free network port and launch the users browser on
http://localhost:port. If port is specified, the server is started at the given port and the
browser is not launched.
-tty
Unix only. Switches controlling the terminal for allowing single-character commands to the
tracer and get single char/1. By default, manipulating the terminal is enabled unless
the system detects it is not connected to a terminal or it is running as a GNU-Emacs inferior
process. See also tty control.
--win app
This option is available only in swipl-win.exe and is used for the start-menu item. If
causes plwin to start in the folder ...\My Documents\Prolog or local equivalent
thereof (see win folder/2). The Prolog subdirectory is created if it does not exist.
-O
Optimised compilation. See current prolog flag/2 flag optimise for details.
-s file
Use file as a script file. The script file is loaded after the initialisation file specified with the
-f file option. Unlike -f file, using -s does not stop Prolog from loading the personal
initialisation file.
-f file
Use file as initialisation file instead of the default .swiplrc (Unix) or swipl.ini (Win-
dows). -f none stops SWI-Prolog from searching for a startup file. This option can be
used as an alternative to -s file that stops Prolog from loading the personal initialisation
file. See also section 2.2.
-F script
Select a startup script from the SWI-Prolog home directory. The script file is named
hscripti.rc. The default script name is deduced from the executable, taking the leading
alphanumerical characters (letters, digits and underscore) from the program name. -F none
stops looking for a script. Intended for simple management of slightly different versions. One
could, for example, write a script iso.rc and then select ISO compatibility mode using
pl -F iso or make a link from iso-pl to pl.
-x bootfile
Boot from bootfile instead of the systems default boot file. A boot file is a file re-
sulting from a Prolog compilation using the -b or -c option or a program saved using
qsave program/[1,2].
-p alias=path1[:path2 . . . ]
Define a path alias for file search path. alias is the name of the alias, and argpath1 ... is a
list of values for the alias. On Windows the list separator is ;. On other systems it is :. A
value is either a term of the form alias(value) or pathname. The computed aliases are added to
file search path/2 using asserta/1, so they precede predefined values for the alias.
See file search path/2 for details on using this file location mechanism.
--traditional
This flag disables the most important extensions of SWI-Prolog version 7 (see section 5) that
introduce incompatibilities with earlier versions. In particular, lists are represented in the
traditional way, double quoted text is represented by a list of character codes and the functional
notation on dicts is not supported. Dicts as a syntactic entity, and the predicates that act on
them, are still supported if this flag is present.
--
Stops scanning for more arguments, so you can pass arguments for your application after this
one. See current prolog flag/2 using the flag argv for obtaining the command line
arguments.
$ swipl -L8m
$ swipl -G32g
-Gsize[kmg]
Limit for the global stack (sometimes also called term stack or heap). This is where compound
terms and large numbers live.
-Lsize[kmg]
Limit for the local stack (sometimes also called environment stack). This is where environments
and choice points live.
-Tsize[kmg]
Limit for the trail stack. This is where we keep track of assignments, so we can rollback on
backtracking or exceptions.
-Msize[kmg]
Limit for the table space. This is where tries holding memoized4 answers for tabling are
stored. The default is 1Gb on 64-bit machines and 512Mb on 32-bit machines. See the Prolog
flag table space
-t goal
Use goal as interactive top level instead of the default goal prolog/0. The goal can be a
complex term. If the top-level goal succeeds SWI-Prolog exits with status 0. If it fails the exit
status is 1. If the top level raises an exception, this is printed as an uncaught error and the
top level is restarted. This flag also determines the goal started by break/0 and abort/0.
If you want to prevent the user from entering interactive mode, start the application with
-g goal -t halt.
-o output
Used in combination with -c or -b to determine output file for compilation.
-b initfile . . . -c file . . .
Boot compilation. initfile . . . are compiled by the C-written bootstrap compiler, file . . . by the
normal Prolog compiler. System maintenance only.
-d token1,token2,...
Print debug messages for DEBUG statements tagged with one of the indicated tokens. Only
has effect if the system is compiled with the -DO DEBUG flag. System maintenance only.
4
The letter M is used because the T was already in use. It is a memnonic for Memoizing.
https://bruda.ca/emacs/prolog_mode_for_emacs
Prolog mode for Emacs and XEmacs maintained by Stefan Bruda.
https://www.metalevel.at/pceprolog/
Recommended configuration options for editing Prolog code with Emacs.
https://www.metalevel.at/ediprolog/
Interact with SWI-Prolog directly in Emacs buffers.
https://www.metalevel.at/etrace/
Trace Prolog code with Emacs.
help
Equivalent to help(help/1).
help(+What)
Show specified part of the manual. What is one of:
Examples:
apropos(+Pattern)
Display all predicates, functions and sections that have Pattern in their name or summary
description. Lowercase letters in Pattern also match a corresponding uppercase letter. Example:
explain(+ToExplain)
Give an explanation on the given object. The argument may be any Prolog data object. If the
argument is an atom, a term of the form Name/Arity or a term of the form Module:Name/Arity,
explain/1 describes the predicate as well as possible references to it. See also gxref/0.
explain(+ToExplain, -Explanation)
Unify Explanation with an explanation for ToExplain. Backtracking yields further explanations.
:- set_prolog_flag(history, 50).
The history system allows the user to compose new queries from those typed before and remembered
by the system. The available history commands are shown in table 2.1. History expansion is not done
if these sequences appear in quoted atoms or strings.
2 ?- format(sn, [$X]).
ifmmp
true.
3 ?-
6 ?- X = statistics.
X = statistics.
7 ?- $X.
28.00 seconds cpu time for 183,128 inferences
4,016 atoms, 1,904 functors, 2,042 predicates, 52 modules
55,915 byte codes; 11,239 external references
min_numlist([H|T], Min) :-
min_numlist(T, H, Min).
1 ?- visible(+all), leash(-exit).
true.
Figure 2.2: Example trace of the program above showing all ports. The lines marked indicate calls
to transparent predicates. See section 6.
+ (Spy)
Set a spy point (see spy/1) on the current predicate.
- (No spy)
Remove the spy point (see nospy/1) from the current predicate.
/ (Find)
Search for a port. After the /, the user can enter a line to specify the port to search for. This
line consists of a set of letters indicating the port type, followed by an optional term, that should
unify with the goal run by the port. If no term is specified it is taken as a variable, searching for
any port of the specified type. If an atom is given, any goal whose functor has a name equal to
that atom matches. Examples:
. (Repeat find)
Repeat the last find command (see /).
A (Alternatives)
Show all goals that have alternatives.
C (Context)
Toggle Show Context. If on, the context module of the goal is displayed between square
brackets (see section 6). Default is off.
L (Listing)
List the current predicate with listing/1.
a (Abort)
Abort Prolog execution (see abort/0).
b (Break)
Enter a Prolog break environment (see break/0).
c (Creep)
Continue execution, stop at next port. (Also RETURN, SPACE).
d (Display)
Set the max depth(Depth) option of debugger write options, limiting the depth to
which terms are printed. See also the w and p options.
e (Exit)
Terminate Prolog (see halt/0).
f (Fail)
Force failure of the current goal.
g (Goals)
Show the list of parent goals (the execution stack). Note that due to tail recursion optimization
a number of parent goals might not exist any more.
h (Help)
Show available options (also ?).
i (Ignore)
Ignore the current goal, pretending it succeeded.
l (Leap)
Continue execution, stop at next spy point.
n (No debug)
Continue execution in no debug mode.
p (Print)
Set the Prolog flag debugger write options to [quoted(true),
portray(true), max depth(10), priority(699)]. This is the default.
r (Retry)
Undo all actions (except for database and I/O actions) back to the call port of the current goal
and resume execution at the call port.
s (Skip)
Continue execution, stop at the next port of this goal (thus skipping all calls to children of this
goal).
u (Up)
Continue execution, stop at the next port of the parent goal (thus skipping this goal and all
calls to children of this goal). This option is useful to stop tracing a failure driven loop.
w (Write)
Set the Prolog flag debugger write options to [quoted(true),
attributes(write), priority(699)], bypassing portray/1, etc.
The ideal 4-port model [Byrd, 1980] as described in many Prolog books
[Clocksin & Melish, 1987] is not visible in many Prolog implementations because code opti-
misation removes part of the choice and exit points. Backtrack points are not shown if either the goal
succeeded deterministically or its alternatives were removed using the cut. When running in debug
mode (debug/0) choice points are only destroyed when removed by the cut. In debug mode, last
call optimisation is switched off.6
Reference information to all predicates available for manipulating the debugger is in section 4.39.
6
This implies the system can run out of stack in debug mode, while no problems arise when running in non-debug mode.
2.10 Compilation
2.10.1 During program development
During program development, programs are normally loaded using the list abbreviation (?-
[load].). It is common practice to organise a project as a collection of source files and a load
file, a Prolog file containing only use module/[1,2] or ensure loaded/1 directives, possi-
bly with a definition of the entry point of the program, the predicate that is normally used to start the
program. This file is often called load.pl. If the entry point is called go, a typical session starts as:
% swipl
<banner>
1 ?- [load].
<compilation messages>
true.
2 ?- go.
<program interaction>
When using Windows, the user may open load.pl from the Windows explorer, which will cause
swipl-win.exe to be started in the directory holding load.pl. Prolog loads load.pl before
entering the top level. If Prolog is started from an interactive shell, one may choose the type swipl
-s load.pl.
Using PrologScript
A Prolog source file can be used directly as a Unix program using the Unix #! magic start. The same
mechanism is useful for specifying additional parameters for running a Prolog file on Windows. The
Unix #! magic is allowed because if the first letter of a Prolog file is #, the first line is treated as
a comment.7 To create a Prolog script, use one of the two alternatives below as first line. The first
can be used to bind a script to a specific Prolog installation, while the latter uses the default prolog
installed in $PATH.
!/path/to/swipl
!/usr/bin/env swipl
The interpretation of arguments to the executable in the HashBang line differs between Unix-derived
systems. For portability, the #! must be followed immediately with an absolute path to the executable
7
The #-sign can be the legal start of a normal Prolog clause. In the unlikely case this is required, leave the first line blank
or add a header comment.
and should have none or one argument. Neither the executable path, nor the argument shall use quotes
or spaces. When started this way, the Prolog flag argv contains the command line arguments that
follow the script invocation. Below is a simple script doing expression evaluation:
#!/usr/bin/env swipl
:- initialization main.
eval :-
current_prolog_flag(argv, Argv),
concat_atom(Argv, , SingleArg),
term_to_atom(Term, SingleArg),
Val is Term,
format(wn, [Val]).
main :-
catch(eval, E, (print_message(error, E), fail)),
halt.
main :-
halt(1).
% ./eval 1+2
3
% ./eval foo
ERROR: is/2: Arithmetic: foo/0 is not a function
%
#!/bin/sh
base=<absolute-path-to-source>
PL=swipl
8
Older versions extracted command line arguments from the HashBang line. As of version 5.9 all relevant setup can
be achieved using directives. Due to the compatibility issues around HashBang line processing, we decided to remove it
completely.
:- initialization go.
go :-
current_prolog_flag(argv, Arguments),
go(Arguments).
go(Args) :-
...
On Windows systems, similar behaviour can be achieved by creating a shortcut to Prolog, passing the
proper options or writing a .bat file.
The options argument are options to qsave program/2 written in the format below. The option
names and their values are described with qsave program/2.
--option-name=option-value
For example, to create a stand-alone executable that starts by executing main/0 and for which
the source is loaded through load.pl, use the command
% swipl
<banner>
?- [load].
?- qsave_program(myprog,
[ goal(main),
stand_alone(true)
]).
?- halt.
( current_prolog_flag(windows, true)
-> <Do MS-Windows things>
; <Do normal things>
)
Some Prolog flags are scoped to a source file. This implies that if they are set using a direc-
tive inside a file, the flag value encountered when loading of the file started is restored when
loading of the file is completed. Currently, the following flags are scoped to the source file:
generate debug info and optimise.
A new thread (see section 9) copies all flags from the thread that created the new thread (its
parent).10 As a consequence, modifying a flag inside a thread does not affect other threads.
10
This is implemented using the copy-on-write tecnhnique.
Later versions might imply various other optimisations such as integrating small predi-
cates into their callers, eliminating constant expressions and other predictable constructs.
Source code optimisation is never applied to predicates that are declared dynamic (see
dynamic/1).
os argv (list, changeable)
List is a list of atoms representing the command line arguments used to invoke SWI-
Prolog. Please note that all arguments are included in the list returned. See argv to get
the application options.
pid (int)
Process identifier of the running Prolog process. Existence of this flag is implementation-
defined.
pipe (bool, changeable)
If true, open(pipe(command), mode, Stream), etc. are supported. Can be
changed to disable the use of pipes in applications testing this feature. Not recommended.
print write options (term, changeable)
Specifies the options for write term/2 used by print/1 and print/2.
prompt alternatives on (atom, changeable)
Determines prompting for alternatives in the Prolog top level. Default is determinism,
which implies the system prompts for alternatives if the goal succeeded while leaving
choice points. Many classical Prolog systems behave as groundness: they prompt for
alternatives if and only if the query contains variables.
protect static code (bool, changeable)
If true (default false), clause/2 does not operate on static code, providing some
basic protection from hackers that wish to list the static code of your Prolog program.
Once the flag is true, it cannot be changed back to false. Protection is default in
ISO mode (see Prolog flag iso). Note that many parts of the development environment
require clause/2 to work on static code, and enabling this flag should thus only be
used for production code.
qcompile (atom, changeable)
This option provides the default for the qcompile(+Atom) option of load files/2.
readline (atom, changeable)
Specifies which form of command line editing is provided. Possible values are below. The
flag may be set from the users init file (see section 2.3) to one of false, readline or
editline. This causes the toplevel not to load a command line editor (false) or load
the specified one. If loading fails the flag is set to false.
false
No command line editing is available.
readline
The library readline is loaded, providing line editing based on the GNU readline
library.
editline
The library editline is loaded, providing line editing based on the BSD libedit.
This is the default if editline is available and can be loaded.
swipl win
SWI-Prolog uses its own console (swipl-win.exe on Windows, the Qt based
swipl-win on MacOS) which provides line editing.
resource database (atom)
Set to the absolute filename of the attached state. Typically this is the file boot32.prc,
the file specified with -x or the running executable. See also resource/3.
report error (bool, changeable)
If true, print error messages; otherwise suppress them. May be changed. See also the
debug on error Prolog flag. Default is true, except for the runtime version.
runtime (bool)
If present and true, SWI-Prolog is compiled with -DO RUNTIME, disabling various
useful development features (currently the tracer and profiler).
sandboxed load (bool, changeable)
If true (default false), load files/2 calls hooks to allow library(sandbox) to
verify the safety of directives.
saved program (bool)
If present and true, Prolog has been started from a state saved with
qsave program/[1,2].
shared object extension (atom)
Extension used by the operating system for shared objects. .so for most Unix systems
and .dll for Windows. Used for locating files using the file type executable.
See also absolute file name/3.
shared object search path (atom)
Name of the environment variable used by the system to search for shared objects.
signals (bool)
Determine whether Prolog is handling signals (software interrupts). This flag is false
if the hosting OS does not support signal handling or the command line option
-nosignals is active. See section 11.4.21 for details.
stream type check (atom, changeable)
Defines whether and how strictly the system validates that byte I/O should not be applied
to text streams and text I/O should not be applied to binary streams. Values are false
(no checking), true (full checking) and loose. Using checking mode loose (default),
the system accepts byte I/O from text stream that use ISO Latin-1 encoding and accepts
writing text to binary streams.
system thread id (int)
Available in multithreaded version (see section 9) where the operating system provides
system-wide integer thread identifiers. The integer is the thread identifier used by the
operating system for the calling thread. See also thread self/1.
table space (integer, changeable)
Space reserved for storing answer tables for tabled predicates (see table/1).16 When
exceeded a resource error(table space) exception is raised.
16
BUG: Currently only counts the space occupied by the nodes in the answer tries.
timezone (integer)
Offset in seconds west of GMT of the current time zone. Set at initialization time
from the timezone variable associated with the POSIX tzset() function. See also
format time/3.
toplevel mode (atom, changeable)
If backtracking (default), the toplevel backtracks after completing a query. If
recursive, the toplevel is implemented as a recursive loop. This implies that global
variables set using b setval/2 are maintained between queries. In recursive mode,
answers to toplevel variables (see section 2.8) are kept in backtrackable global variables
and thus not copied. In backtracking mode answers to toplevel variables are kept in the
recorded database (see section 4.14.2).
The recursive mode has been added for interactive usage of CHR (see section 8),17 which
maintains the global constraint store in backtrackable global variables.
toplevel print anon (bool, changeable)
If true, top-level variables starting with an underscore ( ) are printed normally. If false
they are hidden. This may be used to hide bindings in complex queries from the top level.
toplevel print factorized (bool, changeable)
If true (default false) show the internal sharing of subterms in the answer substi-
tution. The example below reveals internal sharing of leaf nodes in red-black trees as
implemented by the rbtrees predicate rb new/1:
?- set_prolog_flag(toplevel_print_factorized, true).
?- rb_new(X).
X = t(_S1, _S1), % where
_S1 = black(, _G387, _G388, ).
If this flag is false, the % where notation is still used to indicate cycles as illustrated
below. This example also shows that the implementation reveals the internal cycle length,
and not the minimal cycle length. Cycles of different length are indistinguishable in Prolog
(as illustrated by S == R).
?- S = s(S), R = s(s(R)), S == R.
S = s(S),
R = s(s(R)).
traditional (bool)
Available in SWI-Prolog version 7. If true, traditional mode has been selected using
--traditional. Notice that some SWI7 features, like the functional notation on
dicts, do not work in this mode. See also section 5.
tty control (bool, changeable)
Determines whether the terminal is switched to raw mode for get single char/1,
which also reads the user actions for the trace. May be set. If this flag is false at
startup, command line editing is disabled. See also the +/-tty command line option.
unix (bool)
If present and true, the operating system is some version of Unix. Defined if the C
compiler used to compile this version of SWI-Prolog either defines __unix__ or unix.
On other systems this flag is not available. See also apple and windows.
unknown (fail,warning,error, changeable)
Determines the behaviour if an undefined procedure is encountered. If fail, the pred-
icate fails silently. If warn, a warning is printed, and execution continues as if the
predicate was not defined, and if error (default), an existence error exception is
raised. This flag is local to each module and inherited from the modules import-module.
Using default setup, this implies that normal modules inherit the flag from user, which
in turn inherit the value error from system. The user may change the flag for module
user to change the default for all application modules or for a specific module. It is
strongly advised to keep the error default and use dynamic/1 and/or multifile/1
to specify possible non-existence of a predicate.
unload foreign libraries (bool, changeable)
If true (default false), unload all loaded foreign libraries. Default is false because
modern OSes reclaim the resources anyway and unloading the foreign code may cause
registered hooks to point to no longer existing data or code.
user flags (Atom, changeable)
Define the behaviour of set prolog flag/2 if the flag is not known. Values are
silent, warning and error. The first two create the flag on-the-fly, where
warning prints a message. The value error is consistent with ISO: it raises an
existence error and does not create the flag. See also create prolog flag/3. The
default is silent, but future versions may change that. Developers are encouraged to
use another value and ensure proper use of create prolog flag/3 to create flags
for their library.
var prefix (bool, changeable)
If true (default false), variables must start with an underscore ( ). May be changed.
This flag is local to the module in which it is changed. See section 2.15.1.
verbose (atom, changeable)
This flag is used by print message/2. If its value is silent, messages of type
informational and banner are suppressed. The -q switches the value from the
initial normal to silent.
verbose autoload (bool, changeable)
If true the normal consult message will be printed if a library is autoloaded. By default
this message is suppressed. Intended to be used for debugging purposes.
verbose load (atom, changeable)
Determines messages printed for loading (compiling) Prolog files. Current values are
full (print a message at the start and end of each file loaded), normal (print a message
at the end of each file loaded), brief (print a message at end of loading the toplevel
file), and silent (no messages are printed, default). The value of this flag is normally
controlled by the option silent(Bool) provided by load files/2.
verbose file search (bool, changeable)
If true (default false), print messages indicating the progress of
absolute file name/[2,3] in locating files. Intended for debugging com-
plicated file-search paths. See also file search path/2.
version (integer)
The version identifier is an integer with value:
filesecurity
Use the Windows GetFileSecurity() function. This does not work on all file systems,
but is probably the best choice on file systems that do support it, notably local NTFS
volumes.
openclose
Try to open the file and close it. This works reliable for files, but not for directories.
Currently directories are checked using waccess(). This is the default.
windows (bool)
If present and true, the operating system is an implementation of Microsoft Windows.
This flag is only available on MS-Windows based versions. See also unix.
write attributes (atom, changeable)
Defines how write/1 and friends write attributed variables. The option values are
described with the attributes option of write term/3. Default is ignore.
write help with overstrike (bool)
Internal flag used by help/1 when writing to a terminal. If present and true it prints
bold and underlined text using overstrike.
xpce (bool)
Available and set to true if the XPCE graphics system is loaded.
xpce version (atom)
Available and set to the version of the loaded XPCE system.
xref (bool, changeable)
If true, source code is being read for analysis purposes such as cross-referencing. Oth-
erwise (default) it is being read to be compiled. This flag is used at several places by
term expansion/2 and goal expansion/2 hooks, notably if these hooks use
side effects. See also the libraries prolog source and prolog xref.
access(+Access)
Define access rights for the flag. Values are read write and read only. The default
is read write.
type(+Atom)
Define a type restriction. Possible values are boolean, atom, integer, float and
term. The default is determined from the initial value. Note that term restricts the term
to be ground.
keep(+Boolean)
If true, do not modify the flag if it already exists. Otherwise (default), this predicate
behaves as set prolog flag/2 if the flag already exists.
portray/1
Hook into write term/3 to alter the way terms are printed (ISO).
message hook/3
Hook into print message/2 to alter the way system messages are printed (Quin-
tus/SICStus).
message property/2
Hook into print message/2 that defines prefix, output stream, color, etc.
library directory/1
Hook into absolute file name/3 to define new library directories (most Prolog systems).
file search path/2
Hook into absolute file name/3 to define new search paths (Quintus/SICStus).
term expansion/2
Hook into load files/2 to modify read terms before they are compiled (macro-processing)
(most Prolog systems).
goal expansion/2
Same as term expansion/2 for individual goals (SICStus).
prolog load file/2
Hook into load files/2 to load other data formats for Prolog sources from non-file re-
sources. The load files/2 predicate is the ancestor of consult/1, use module/1,
etc.
qpredrefprolog editlocate3
Hook into edit/1 to locate objects (SWI).
qpredrefprolog editedit source1
Hook into edit/1 to call an internal editor (SWI).
qpredrefprologhelp hook1
Hook in help/0, help/1 and apropos/1 to extend the help system.
resource/3
Define a new resource (not really a hook, but similar) (SWI).
exception/3
Old attempt to a generic hook mechanism. Handles undefined predicates (SWI).
The predicate make/0 updates the autoload index. It searches for all library directories
(see library directory/1 and file search path/2) holding the file MKINDEX.pl or
INDEX.pl. If the current user can write or create the file INDEX.pl and it does not exist or
18
Actually, the hook user:exception/3 is called; only if this hook fails does it call the autoloader.
is older than the directory or one of its files, the index for this directory is updated. If the file
MKINDEX.pl exists, updating is achieved by loading this file, normally containing a directive calling
make library index/2. Otherwise make library index/1 is called, creating an index for
all *.pl files containing a module.
Below is an example creating an indexed library directory.
% mkdir /lib/prolog
% cd /lib/prolog
% swipl -g true -t make_library_index(.)
If there is more than one library file containing the desired predicate, the following search schema is
followed:
1. If there is a library file that defines the module in which the undefined predicate is trapped, this
file is used.
2. Otherwise library files are considered in the order they appear in the library directory/1
predicate and within the directory alphabetically.
autoload path(+DirAlias)
Add DirAlias to the libraries that are used by the autoloader. This extends the search path
autoload and reloads the library index. For example:
:- autoload_path(library(http)).
If this call appears as a directive, it is term-expanded into a clause for user:file search path/2 and
a directive calling reload library index/0. This keeps source information and allows
for removing this directive.
:- make_library_index(.,
[ *.pl,
trace/browse.pl
]).
When creating an executable using either qsave program/2 or the -c command line options,
it is necessarry to load all predicates that would normally be autoloaded explicitly. This is discussed
in section 12. See autoload/0.
Nested comments
SWI-Prolog allows for nesting /* ...*/ comments. Where the ISO standard accepts
/* .../* ...*/ as a comment, SWI-Prolog will search for a terminating */. This is useful
if some code with /* ...*/ comment statements in it should be commented out. This modification
also avoids unintended commenting in the example below, where the closing */ of the first comment
has been forgotten.19
19
Recent copies of GCC give a style warning if /* is encountered in a comment, which suggests that this problem has
been recognised more widely.
/* comment
code
/* second comment */
code
\a
Alert character. Normally the ASCII character 7 (beep).
\b
Backspace character.
\c
No output. All input characters up to but not including the first non-layout character are skipped.
This allows for the specification of pretty-looking long lines. Not supported by ISO. Example:
\hNEWLINEi
When in ISO mode (see the Prolog flag iso), only skip this sequence. In native mode, white
space that follows the newline is skipped as well and a warning is printed, indicating that this
construct is deprecated and advising to use \c. We advise using \c or putting the layout
before the \, as shown below. Using \c is supported by various other Prolog implementations
and will remain supported by SWI-Prolog. The style shown below is the most compatible
solution.21
instead of
20
Up to SWI-Prolog 6.1.9, undefined escape characters were copied verbatim, i.e., removing the backslash.
21
Future versions will interpret \hreturni according to ISO.
\e
Escape character (ASCII 27). Not ISO, but widely supported.
\f
Form-feed character.
\n
Next-line character.
\r
Carriage-return only (i.e., go back to the start of the line).
\s
Space character. Intended to allow writing 0\s to get the character code of the space charac-
ter. Not ISO.
\t
Horizontal tab character.
\v
Vertical tab character (ASCII 11).
\xXX..\
Hexadecimal specification of a character. The closing \ is obligatory according to the ISO
standard, but optional in SWI-Prolog to enhance compatibility with the older Edinburgh stan-
dard. The code \xa\3 emits the character 10 (hexadecimal a) followed by 3. Characters
specified this way are interpreted as Unicode characters. See also \u.
\uXXXX
Unicode character specification where the character is specified using exactly 4 hexadecimal
digits. This is an extension to the ISO standard, fixing two problems. First, where \x defines
a numeric character code, it doesnt specify the character set in which the character should be
interpreted. Second, it is not needed to use the idiosyncratic closing \ ISO Prolog syntax.
\UXXXXXXXX
Same as \uXXXX, but using 8 digits to cover the whole Unicode set.
\40
Octal character specification. The rules and remarks for hexadecimal specifications apply to
octal specifications as well.
\\
Escapes the backslash itself. Thus, \\ is an atom consisting of a single \.
\
Single quote. Note that \ and both describe the atom with a single , i.e.,
\ == is true.
\"
Double quote.
\
Back quote.
1_000_000
1 000 000
1_000_/*more*/000
Integers can be printed using this notation with format/2, using the I format specifier. For exam-
ple:
?- format(I, [1000000]).
1_000_000
The current syntax has been proposed by Ulrich Neumerkel on the SWI-Prolog mailinglist.
Infinity is printed as 1.0Inf or -1.0Inf. Any sequence matching the regular expression
[+-]?\sd+[.]\sd+Inf is mapped to plus or minus infinity.
NaN (Not a Number) is printed as 1.xxxNaN, where 1.xxx is the float after replacing the
exponent by 1. Such numbers are read, resulting in the same NaN. The NaN constant can also
be produced using the function nan/0, e.g.,
?- A is nan.
A = 1.5NaN.
Note that, compliant with the ISO standard, SWI-Prolog arithmetic (see section 4.27) never returns
one of the above values but instead raises an exception, e.g.,
?- A is 1/0.
ERROR: //2: Arithmetic: evaluation error: zero_divisor
There is one exception to this rule. For compatibility the functions inf/0 and nan/0 return 1.0Inf
and the default system NaN. The ability to create, read and write such values is primarily provided to
exchange data with languages that can represent the full range of IEEE doubles.
According to the ISO standard and most Prolog systems, identifiers that start with an uppercase letter
or an underscore are variables. In the past, Prolog by BIM provided an alternative syntax, where
only the underscore ( ) introduces a variable. As of SWI-Prolog 7.3.27 SWI-Prolog supports this
alternative syntax, controlled by the Prolog flag var prefix. As the character escapes flag,
this flag is maintained per module, where the default is false, supporting standard syntax.
Having only the underscore introduce a variable is particularly useful if code contains identifiers
for case sensitive external languages. Examples are the RDF library where code frequently specifies
property and class names22 and the R interface for specifying functions or variables that start with an
uppercase character. Lexical databases were part of the terms start with an uppercase letter is another
category were the readability of the code improves using this option.
The ISO standard specifies the Prolog syntax in ASCII characters. As SWI-Prolog supports Unicode
in source files we must extend the syntax. This section describes the implication for the source files,
while writing international source files is described in section 3.1.3.
The SWI-Prolog Unicode character classification is based on version 6.0.0 of the Unicode stan-
dard. Please note that char type/2 and friends, intended to be used with all text except Prolog
source code, is based on the C library locale-based classification routines.
White space
All characters marked as separators (Z*) in the Unicode tables are handled as layout characters.
Other characters
The first 128 characters follow the ISO Prolog standard. Unicode symbol and punctuation
characters (general category S* and P*) act as glueing symbol characters (i.e., just like ==: an
unquoted sequence of symbol characters are combined into an atom).
Other characters (this is mainly No: a numeric character of other type) are currently handled as
solo.
A singleton variable is a variable that appears only one time in a clause. It can always be replaced
by _, the anonymous variable. In some cases, however, people prefer to give the variable a name.
As mistyping a variable is a common mistake, Prolog systems generally give a warning (controlled
by style check/1) if a variable is used only once. The system can be informed that a variable is
meant to appear once by starting it with an underscore, e.g., _Name. Please note that any variable,
except plain _, shares with variables of the same name. The term t(_X, _X) is equivalent to
t(X, X), which is different from t(_, _).
As Unicode requires variables to start with an underscore in many languages, this schema needs
to be extended.24 First we define the two classes of named variables.
Normal variables
All other variables are normal variables. Note this makes _var a normal variable.25
Any normal variable appearing exactly once in the clause and any named singleton variables
appearing more than once are reported. Below are some examples with warnings in the right column.
Singleton messages can be suppressed using the style check/1 directive.
23
http://www.unicode.org/reports/tr31/
24
After a proposal by Richard OKeefe.
25
Some Prolog dialects write variables this way.
test( ).
test( a). Singleton variables: [ a]
test( 12). Singleton variables: [ 12]
test(A). Singleton variables: [A]
test( A).
test( a).
test( , ).
test( a, a).
test( a, a). Singleton-marked variables appearing more than once: [ a]
test( A, A). Singleton-marked variables appearing more than once: [ A]
test(A, A).
Semantic singletons Starting with version 6.5.1, SWI-Prolog has syntactic singletons and seman-
tic singletons. The first are checked by read clause/3 (and read term/3 using the option
singletons(warning)). The latter are generated by the compiler for variables that appear alone in
a branch. For example, in the code below the variable X is not a syntactic singleton, but the variable
X does not communicate any bindings and replacing X with does not change the semantics.
test :-
( test_1(X)
; test_2(X)
).
1 ?- A = f(A), asserta(a(A)).
ERROR: asserta/1: Cannot represent due to cyclic_term
2 ?- A = 1+A, B is A.
Hash lookup
If none of the above applies, the system considers the available hash tables for which the corre-
sponding argument is instantiated. If a table is found with acceptable characteristics, it is used.
Otherwise, there are two cases. First, if no hash table is available for the instantiated arguments,
it assesses the clauses for all instantiated arguments and selects the best candidate for creating
a hash table. Arguments that cannot be indexed are flagged to avoid repeated scanning. Sec-
ond, if there is a hash table for an indexed argument but it has poor characteristics, the system
scans other instantiated arguments to see whether it can create a better hash table. The system
maintains a bit vector on each table in which it marks arguments that are less suitable than the
argument to which the table belongs.
Clauses that have a variable at an otherwise indexable argument must be linked into all hash
buckets. Currently, predicates that have more than 10% such clauses for a specific argument are
not considered for indexing on that argument.
Disregarding variables, the suitability of an argument for hashing is expressed as the number of
unique indexable values divided by the standard deviation of the number of duplicate values for
each value plus one.27
The indexes of dynamic predicates are deleted if the number of clauses is doubled since
its creation or reduced below 1/4th. The JIT approach will recreate a suitable index on
26
JIT indexing was added in version 5.11.29 (Oct. 2011).
27
Earlier versions simply used the number of unique values, but poor distribution of values makes a table less suitable.
This was analysed by Fabien Noth and Gunter Kniesel.
the next call. Indexes of running predicates cannot be deleted. They are added to a re-
moved index list associated to the predicate. Outdated indexes of predicates are reclaimed
by garbage collect clauses/0. The clause garbage collector is scheduled automati-
cally, based on time and space based heuristics. See garbage collect clauses/0 for
details.
stream. The most popular one, especially in the context of the web, is UTF-8. Bytes 0 . . . 127
represent simply the corresponding US-ASCII character, while bytes 128 . . . 255 are used for multi-
byte encoding of characters placed higher in the UCS space. Especially on MS-Windows the 16-bit
Unicode standard, represented by pairs of bytes, is also popular.
Prolog I/O streams have a property called encoding which specifies the used encoding that influ-
ences get code/2 and put code/2 as well as all the other text I/O predicates.
The default encoding for files is derived from the Prolog flag encoding, which is initialised
from the environment. If the environment variable LANG ends in UTF-8, this encoding is as-
sumed. Otherwise the default is text and the translation is left to the wide-character functions
of the C library.28 The encoding can be specified explicitly in load files/2 for loading Prolog
source with an alternative encoding, open/4 when opening files or using set stream/2 on any
open stream. For Prolog source files we also provide the encoding/1 directive that can be used
to switch between encodings that are compatible with US-ASCII (ascii, iso latin 1, utf8
and many locales). See also section 3.1.3 for writing Prolog files with non-US-ASCII characters
and section 2.15.1 for syntax issues. For additional information and Unicode resources, please visit
http://www.unicode.org/.
SWI-Prolog currently defines and supports the following encodings:
octet
Default encoding for binary streams. This causes the stream to be read and written fully
untranslated.
ascii
7-bit encoding in 8-bit bytes. Equivalent to iso latin 1, but generates errors and warnings
on encountering values above 127.
iso latin 1
8-bit encoding supporting many Western languages. This causes the stream to be read and
written fully untranslated.
text
C library default locale encoding for text files. Files are read and written using the C library
functions mbrtowc() and wcrtomb(). This may be the same as one of the other locales, notably
it may be the same as iso latin 1 for Western languages and utf8 in a UTF-8 context.
utf8
Multi-byte encoding of full UCS, compatible with ascii. See above.
unicode be
Unicode Big Endian. Reads input in pairs of bytes, most significant byte first. Can only repre-
sent 16-bit characters.
unicode le
Unicode Little Endian. Reads input in pairs of bytes, least significant byte first. Can only
represent 16-bit characters.
Note that not all encodings can represent all characters. This implies that writing text to a stream
may cause errors because the stream cannot represent these characters. The behaviour of a stream
28
The Prolog native UTF-8 mode is considerably faster than the generic mbrtowc() one.
on these errors can be controlled using set stream/2. Initially the terminal stream writes the
characters using Prolog escape sequences while other streams generate an I/O exception.
From section 2.18.1, you may have got the impression that text files are complicated. This section
deals with a related topic, making life often easier for the user, but providing another worry to the
programmer. BOM or Byte Order Marker is a technique for identifying Unicode text files as well as
the encoding they use. Such files start with the Unicode character 0xFEFF, a non-breaking, zero-width
space character. This is a pretty unique sequence that is not likely to be the start of a non-Unicode
file and uniquely distinguishes the various Unicode file formats. As it is a zero-width blank, it even
doesnt produce any output. This solves all problems, or . . .
Some formats start off as US-ASCII and may contain some encoding mark to switch to UTF-8,
such as the encoding="UTF-8" in an XML header. Such formats often explicitly forbid the use
of a UTF-8 BOM. In other cases there is additional information revealing the encoding, making the
use of a BOM redundant or even illegal.
The BOM is handled by SWI-Prolog open/4 predicate. By default, text files are probed for the
BOM when opened for reading. If a BOM is found, the encoding is set accordingly and the property
bom(true) is available through stream property/2. When opening a file for writing, writing a
BOM can be requested using the option bom(true) with open/4.
The heap
With the heap, we refer to the memory area used by malloc() and friends. SWI-Prolog uses the area
to store atoms, functors, predicates and their clauses, records and other dynamic data. No limits are
imposed on the addresses returned by malloc() and friends.
Atoms and Strings SWI-Prolog has no limits on the sizes of atoms and strings. read/1 and its
derivatives, however, normally limit the number of newlines in an atom or string to 6 to improve
error detection and recovery. This can be switched off with style check/1.
The number of atoms is limited to 16777216 (16M) on 32-bit machines. On 64-bit machines
this is virtually unlimited. See also section 11.4.2.
Memory areas On 32-bit hardware, SWI-Prolog data is packed in a 32-bit word, which contains both
type and value information. The size of the various memory areas is limited to 128 MB for each
of the areas, except for the program heap, which is not limited. On 64-bit hardware there are no
meaningful limits.
Nesting of terms Most built-in predicates that process Prolog terms create an explicitly managed
stack and perform optimization for processing the last argument of a term. This implies they
can process deeply nested terms at constant and low usage of the C stack, and the system raises
a resource error if no more stack can be allocated. Currently only read/1 and write/1 (and
all variations thereof) still use the C stack and may cause the system to crash in an uncontrolled
way (i.e., not mapped to a Prolog exception that can be caught).
Integers On most systems SWI-Prolog is compiled with support for unbounded integers by means of
the GNU GMP library. In practice this means that integers are bound by the global stack size.
Too large integers cause a resource error. On systems that lack GMP, integers are 64-bit
on 32- as well as 64-bit machines.
Integers up to the value of the max tagged integer Prolog flag are represented
more efficiently on the stack. For integers that appear in clauses, the value (below
max tagged integer or not) has little impact on the size of the clause.
Floating point numbers Floating point numbers are represented as C-native double precision floats,
64-bit IEEE on most machines.
If the system is tight on physical memory, 32-bit Prolog has the clear advantage of using only
slightly more than half of the memory of 64-bit Prolog. This argument applies as long as the applica-
tion fits in the virtual address space of the machine. The virtual address space of 32-bit hardware is
4GB, but in many cases the operating system provides less to user applications.
The only standard SWI-Prolog library adding significantly to this calculation is the RDF database
provided by the semweb package. It uses approximately 80 bytes per triple on 32-bit hardware and
150 bytes on 64-bit hardware. Details depend on how many different resources and literals appear in
the dataset as well as desired additional literal indexes.
Summarizing, if applications are small enough to fit comfortably in virtual and physical memory,
simply take the model used by most of the applications on the OS. If applications require more than
128 MB per stack, use the 64-bit edition. If applications approach the size of physical memory, fit
in the 128 MB stack limit and fit in virtual memory, the 32-bit version has clear advantages. For
demanding applications on 64-bit hardware with more than about 6GB physical memory the 64-bit
model is the model of choice.
Project Directories
Large projects are generally composed of sub-projects, each using its own directory or directory struc-
ture. If nobody else will ever touch your files and you use only one computer, there is little to worry
:- prolog_load_context(directory, Dir),
asserta(user:file_search_path(myapp, Dir)).
user:file_search_path(graph, myapp(graph)).
user:file_search_path(ui, myapp(ui)).
When using sub-projects in the SWI-Prolog hierarchy, one should use the path alias swi as basis. For
a system-wide installation, use an absolute path.
Extensive sub-projects with a small well-defined API should define a load file with calls to
use module/1 to import the various library components and export the API.
load.pl
Use this file to set up the environment (Prolog flags and file search paths) and load the sources.
Quite commonly this file also provides convenient predicates to parse command line options
and start the application.
run.pl
Use this file to start the application. Normally it loads load.pl in silent-mode, and calls one
of the starting predicates from load.pl.
save.pl
Use this file to create a saved state of the application by loading load.pl and calling
qsave program/2 to generate a saved state with the proper options.
debug.pl
Loads the program for debugging. In addition to loading load.pl this file defines rules for
portray/1 to modify printing rules for complex terms and customisation rules for the debug-
ger and editing environment. It may start some of these tools.
Using modules is generally easy. Only if you write meta-predicates (predicates reasoning about
other predicates) that are exported from a module is a good understanding required of the resolution
of terms to predicates inside a module. Here is a typical example from readutil.
:- module(read_util,
[ read_line_to_codes/2, % +Fd, -Codes
read_line_to_codes/3, % +Fd, -Codes, ?Tail
read_stream_to_codes/2, % +Fd, -Codes
read_stream_to_codes/3, % +Fd, -Codes, ?Tail
read_file_to_codes/3, % +File, -Codes, +Options
read_file_to_terms/3 % +File, -Terms, +Options
]).
If multiple matches are found it provides a choice. Together with the built-in completion on atoms
bound to the TAB key this provides a quick way to edit objects:
?- edit(country).
Please select item to edit:
1 chat:country/10 /staff/jan/lib/prolog/chat/countr.pl:16
2 chat:country/1 /staff/jan/lib/prolog/chat/world0.pl:72
Your choice?
?- edit(prove).
Now edit the source, possibly switching to other files and making multiple changes. After finishing,
invoke make/0, either through the editor UI (Compile/Make (Control-C Control-M)) or on
the top level, and watch the files being reloaded.2
?- make.
% show compiled into photo_gallery 0.03 sec, 3,360 bytes
Edit modes
Modes are the heart of (Pce)Emacs. Modes define dedicated editing support for a particular kind of
(source) text. For our purpose we want Prolog mode. There are various ways to make PceEmacs use
Prolog mode for a file.
Using #!/path/to/.../swipl
If the file is a Prolog Script file, starting with the line #!/path/to/swipl options, Prolog
mode is selected regardless of the extension.
Explicit selection
Finally, using File/Mode/Prolog you can switch to Prolog mode explicitly.
Cut/Copy/Paste
These commands follow Unix/X11 traditions. Youre best suited with a three-button mouse.
After selecting using the left-mouse (double-click uses word-mode and triple line-mode), the
selected text is automatically copied to the clipboard (X11 primary selection on Unix). Cut is
achieved using the DEL key or by typing something else at the location. Paste is achieved using
the middle-mouse (or wheel) button. If you dont have a middle-mouse button, pressing the
left- and right-button at the same time is interpreted as a middle-button click. If nothing helps,
there is the Edit/Paste menu entry. Text is pasted at the caret location.
Undo
Undo is bound to the GNU-Emacs Control- as well as the MS-Windows Control-Z sequence.
Abort
Multi-key sequences can be aborted at any stage using Control-G.
3
Decent merging with MS-Windows control-key conventions is difficult as many conflict with GNU-Emacs. Especially
the cut/copy/paste commands conflict with important GNU-Emacs commands.
Find
Find (Search) is started using Control-S (forward) or Control-R (backward). PceEmacs imple-
ments incremental search. This is difficult to use for novices, but very powerful once you get
the clue. After one of the above start keys, the system indicates search mode in the status line.
As you are typing the search string, the system searches for it, extending the search with every
character you type. It illustrates the current match using a green background.
If the target cannot be found, PceEmacs warns you and no longer extends the search string.4
During search, some characters have special meaning. Typing anything but these characters
commits the search, re-starting normal edit mode. Special commands are:
Control-S
Search forwards for next.
Control-R
Search backwards for next.
Control-W
Extend search to next word boundary.
Control-G
Cancel search, go back to where it started.
ESC
Commit search, leaving caret at found location.
Backspace
Remove a character from the search string.
Dynamic Abbreviation
Also called dabbrev, dynamic abbreviation is an important feature of Emacs clones to support
programming. After typing the first few letters of an identifier, you may press Alt-/, causing
PceEmacs to search backwards for identifiers that start the same and use it to complete the text
you typed. A second Alt-/ searches further backwards. If there are no hits before the caret, it
starts searching forwards. With some practice, this system allows for entering code very fast
with nice and readable identifiers (or other difficult long words).
Open (a file)
Is called File/Find file (Control-x Control-f). By default the file is loaded into the
current window. If you want to keep this window, press Alt-s or click the little icon at the
bottom left to make the window sticky.
Split view
Sometimes you want to look at two places in the same file. To do this, use Control-x 2 to create
a new window pointing to the same file. Do not worry, you can edit as well as move around in
both. Control-x 1 kills all other windows running on the same file.
These are the most commonly used commands. In section 3.4.3 we discuss specific support for
dealing with Prolog source code.
4
GNU-Emacs keeps extending the string, but why? Adding more text will not make it match.
After typing a .
After typing a . that is not preceded by a symbol character, the system assumes you completed
a clause, tries to find the start of this clause and verifies the syntax. If this process succeeds it
colours the elements of the clause according to the rules given below. Colouring is done using
information from the last full check on this file. If it fails, the syntax error is displayed in the
status line and the clause is not coloured.
The colour schema itself is defined in emacs/prolog colour. The colouring can be extended
and modified using multifile predicates. Please check this source file for details. In general, underlined
objects have a popup (right-mouse button) associated with common commands such as viewing the
documentation or source. Bold text is used to indicate the definition of objects (typically predicates
when using plain Prolog). Other colours follow intuitive conventions. See table 3.4.3.
Layout support Layout is not just nice, it is essential for writing readable code. There is much
debate on the proper layout of Prolog. PceEmacs, being a rather small project, supports only one
particular style for layout.6 Below are examples of typical constructs.
head(arg1, arg2).
head(arg1, arg2) :- !.
head(Arg1, arg2) :- !,
call1(Arg1).
head(Arg1, arg2) :-
5
In most cases the location where the parser cannot proceed is further down the file than the actual error location.
6
Defined in Prolog in the file emacs/prolog mode, you may wish to extend this. Please contribute your extensions!
Clauses
Blue bold Head of an exported predicate
Red bold Head of a predicate that is not called
Black bold Head of remaining predicates
Calls in the clause body
Blue Call to built-in or imported predicate
Red Call to undefined predicate
Purple Call to dynamic predicate
Other entities
Dark green Comment
Dark blue Quoted atom or string
Brown Variable
( if(Arg1)
-> then
; else
).
head(Arg1) :-
( a
; b
).
head :-
a(many,
long,
arguments(with,
many,
more),
and([ a,
long,
list,
with,
a,
| tail
])).
PceEmacs uses the same conventions as GNU-Emacs. The TAB key indents the current line according
to the syntax rules. Alt-q indents all lines of the current clause. It provides support for head, calls
(indented 1 tab), if-then-else, disjunction and argument lists broken across multiple lines as illustrated
above.
guitracer
This predicate installs the above-mentioned hooks that redirect tracing to the window-based
environment. No window appears. The debugger window appears as actual tracing is started
through trace/0, by hitting a spy point defined by spy/1 or a break point defined using the
PceEmacs command Prolog/Break at (Control-c b).
noguitracer
Disable the hooks installed by guitracer/0, reverting to normal text console-based tracing.
gtrace
Utility defined as guitracer,trace.
gdebug
Utility defined as guitracer,debug.
gspy(+Predicate)
Utility defined as guitracer,spy(Predicate).
3.7 Cross-referencer
A cross-referencer is a tool that examines the caller-callee relation between predicates, and, using this
information to explicate dependency relations between source files, finds calls to non-existing pred-
icates and predicates for which no callers can be found. Cross-referencing is useful during program
development, reorganisation, clean-up, porting and other program maintenance tasks. The dynamic
nature of Prolog makes the task non-trivial. Goals can be created dynamically using call/1 after
construction of a goal term. Abstract interpretation can find some of these calls, but they can also come
from external communication, making it impossible to predict the callee. In other words, the cross-
referencer has only partial understanding of the program, and its results are necessarily incomplete.
Still, it provides valuable information to the developer.
SWI-Prologs cross-referencer is split into two parts. The standard Prolog library prolog xref
is an extensible library for information gathering described in section A.26, and the XPCE library
pce xref provides a graphical front-end for the cross-referencer described here. We demonstrate
the tool on CHAT80, a natural language question and answer system by Fernando C.N. Pereira and
David H.D. Warren.
gxref
Run cross-referencer on all currently loaded files and present a graphical overview of the result.
As the predicate operates on the currently loaded application it must be run after loading the
application.
The left window (see figure 3.1) provides browsers for loaded files and predicates. To avoid
long file paths, the file hierarchy has three main branches. The first is the current directory hold-
ing the sources. The second is marked alias, and below it are the file-search-path aliases (see
file search path/2 and absolute file name/3). Here you find files loaded from the sys-
tem as well as modules of the program loaded from other locations using the file search path. All
loaded files that fall outside these categories are below the last branch called /. Files where the
system found suspicious dependencies are marked with an exclamation mark. This also holds for
directories holding such files. Clicking on a file opens a File info window in the right pane.
The File info window shows a file, its main properties, its undefined and not-called predicates and
its import and export relations to other files in the project. Both predicates and files can be opened
by clicking on them. The number of callers in a file for a certain predicate is indicated with a blue
underlined number. A left-click will open a list and allow editing the calling predicate.
The Dependencies (see figure 3.2) window displays a graphical overview of dependencies be-
tween files. Using the background menu a complete graph of the project can be created. It is also
possible to drag files onto the graph window and use the menu on the nodes to incrementally expand
the graph. The underlined blue text indicates the number of predicates used in the destination file.
Left-clicking opens a menu to open the definition or select one of the callers.
Module and non-module files The cross-referencer threads module and non-module project files
differently. Module files have explicit import and export relations and the tool shows the usage and
consistency of the relations. Using the Header menu command, the tool creates a consistent import
list for the module that can be included in the file. The tool computes the dependency relations
between the non-module files. If the user wishes to convert the project into a module-based one,
the Header command generates an appropriate module header and import list. Note that the cross-
referencer may have missed dependencies and does not deal with meta-predicates defined in one
module and called in another. Such problems must be resolved manually.
Settings The following settings can be controlled from the settings menu:
Warn autoload
By default disabled. If enabled, modules that require predicates to be autoloaded are flagged
with a warning and the file info window of a module shows the required autoload predicates.
prolog ide(+Action)
This predicate ensures the IDE-enabling XPCE component is loaded, creates the XPCE class
prolog ide and sends Action to its one and only instance @prolog_ide. Action is one of the
following:
open navigator(+Directory)
Open the Prolog Navigator (see section 3.6) in the given Directory.
open debug status
Open a window to edit spy and trace points.
open query window
Open a little window to run Prolog queries from a GUI component.
thread monitor
Open a graphical window indicating existing threads and their status.
debug monitor
Open a graphical front-end for the debug library that provides an overview of the topics
and catches messages.
xref
Open a graphical front-end for the cross-referencer that provides an overview of predicates
and their callers.
Atom completion
The console7 completes a partial atom on the TAB key and shows alternatives on the command
Alt-?.
Select editor
External editors are selected using the EDITOR environment variable, by setting the Prolog flag
editor, or by defining the hook qpredrefprolog editedit source1.
PceEmacs
Offers syntax highlighting and checking based on real-time parsing of the editors buffer, layout
support and navigation support.
7
On Windows this is realised by swipl-win.exe, on Unix through the GNU readline library, which is included automati-
cally when found by configure.
++ Argument must be ground, i.e., the argument may not contain a variable
anywhere.
+ Argument must be fully instantiated to a term that satisfies the type.
This is not necessarily ground, e.g., the term [ ] is a list, although its
only member is unbound.
- Argument is an output argument. Unless specified otherwise,
output arguments need not to be unbound. For example, the
goal findall(X, Goal, [T]) is good style and equivalent to
findall(X, Goal, Xs), Xs = [T]2 Note that the determin-
ism specification, e.g., det only applies if this argument is unbound.
Argument must be unbound. Typically used by predicates that create
something and return a handle to the created object, such as open/3
which creates a stream.
? Argument must be bound to a partial term of the indicated type.
Note that a variable is a partial term for any type. Think of the
argument as either input or output or both input and output. For
example, in stream property(S, reposition(Bool)), the
reposition part of the term is input and the uninstantiated Bool is
output.
: Argument is a meta-argument. Implies +. See chapter 6 for more infor-
mation on module handling.
@ Argument is not further instantiated. Typically used for type tests.
! Argument contains a mutable structure that may be modified using
setarg/3 or nb setarg/3.
Referring to a predicate in running text is done using a predicate indicator. The canonical and
most generic form of a predicate indicator is a term hmodulei:hnamei/harityi. If the module is irrele-
vant (built-in predicate) or can be inferred from the context it is often omitted. Compliant to the ISO
standard draft on DCG (see section 4.13), SWI-Prolog also allows for [hmodulei]:hnamei//harityi to
1
These definitions are taken from PlDoc. The current manual has only one mode declaration per predicate and therefore
predicates with mode (+,-) and (-,+) are described as (?,?). The @-mode is often replaced by +.
refer to a grammar rule. For all non-negative arity, hnamei//harityi is the same as hnamei/harityi+2,
regardless of whether or not the referenced predicate is defined or can be used as a grammar rule. The
//-notation can be used in all places that traditionally allow for a predicate indicator, e.g., the module
declaration, spy/1, and dynamic/1.
code
A character code is an integer representing a single character. As files may use multi-byte
encoding for supporting different character sets (utf-8 encoding for example), reading a code
from a text file is in general not the same as reading a byte.
char
Alternatively, characters may be represented as one-character atoms. This is a natural repre-
sentation, hiding encoding problems from the programmer as well as providing much easier
debugging.
byte
Bytes are used for accessing binary streams.
In SWI-Prolog, character codes are always the Unicode equivalent of the encoding. That is,
if get code/1 reads from a stream encoded as KOI8-R (used for the Cyrillic alphabet), it re-
turns the corresponding Unicode code points. Similarly, assembling or disassembling atoms using
atom codes/2 interprets the codes as Unicode points. See section 2.18.1 for details.
To ease the pain of the two character representations (code and char), SWI-Prologs built-in predi-
cates dealing with character data work as flexible as possible: they accept data in any of these formats
as long as the interpretation is unambiguous. In addition, for output arguments that are instantiated,
the character is extracted before unification. This implies that the following two calls are identical,
both testing whether the next input character is an a.
peek_code(Stream, a).
peek_code(Stream, 97).
The two character representations are handled by a large number of built-in predicates,
all of which are ISO-compatible. For converting between code and character there is
char code/2. For breaking atoms and numbers into characters there are atom chars/2,
atom codes/2, number chars/2 and number codes/2. For character I/O on streams
there are get char/[1,2], get code/[1,2], get byte/[1,2], peek char/[1,2],
peek code/[1,2], peek byte/[1,2], put code/[1,2], put char/[1,2] and
put byte/[1,2]. The Prolog flag double quotes controls how text between double quotes is
interpreted.
A traditional Prolog source file contains Prolog clauses and directives, but no module declara-
tion (see module/1). They are normally loaded using consult/1 or ensure loaded/1.
Currently, a non-module file can only be loaded into a single module.3
A module Prolog source file starts with a module declaration. The subsequent Prolog code is loaded
into the specified module, and only the exported predicates are made available to the context
loading the module. Module files are normally loaded with use module/[1,2]. See chap-
ter 6 for details.
An include Prolog source file is loaded using the include/1 directive, textually including Prolog
text into another Prolog source. A file may be included into multiple source files and is typically
used to share declarations such as multifile or dynamic between source files.
Prolog source files are located using absolute file name/3 with the following options:
locate_prolog_file(Spec, Path) :-
absolute_file_name(Spec,
[ file_type(prolog),
access(read)
],
Path).
The file type(prolog) option is used to determine the extension of the file using
prolog file type/2. The default extension is .pl. Spec allows for the path alias construct de-
fined by absolute file name/3. The most commonly used path alias is library(LibraryFile).
The example below loads the library file ordsets.pl (containing predicates for manipulating or-
dered sets).
:- use_module(library(ordsets)).
SWI-Prolog recognises grammar rules (DCG) as defined in [Clocksin & Melish, 1987]. The user
may define additional compilation of the source file by defining the dynamic multifile predicates
term expansion/2, term expansion/4, goal expansion/2 and goal expansion/4.
It is not allowed to use assert/1, retract/1 or any other database predicate in
term expansion/2 other than for local computational purposes.4 Code that needs to create ad-
ditional clauses must use compile aux clauses/1. See library(apply macros) for an
example.
A directive is an instruction to the compiler. Directives are used to set (predicate) properties (see
section 4.15), set flags (see set prolog flag/2) and load files (this section). Directives are terms
of the form :- htermi.. Here are some examples:
3
This limitation may be lifted in the future. Existing limitations in SWI-Prologs source code administration make this
non-trivial.
4
It does work for normal loading, but not for qcompile/1.
Table 4.1: Properties of the file-loading predicates. The import column specifies what is imported if
the loaded file is a module file.
:- use_module(library(lists)).
:- dynamic
store/2. % Name, Value
The directive initialization/1 can be used to run arbitrary Prolog goals. The specified goal is
started after loading the file in which it appears has completed.
SWI-Prolog compiles code as it is read from the file, and directives are executed as goals. This
implies that directives may call any predicate that has been defined before the point where the directive
appears. It also accepts ?- htermi. as a synonym.
SWI-Prolog does not have a separate reconsult/1 predicate. Reconsulting is implied auto-
matically by the fact that a file is consulted which is already loaded.
Advanced topics are handled in subsequent sections: mutually dependent files (section 4.3.2),
multithreaded loading (section 4.3.2) and reloading running code (section 4.3.2).
The core of the family of loading predicates is load files/2. The predicates consult/1,
ensure loaded/1, use module/1, use module/2 and reexport/1 pass the file argument
directly to load files/2 and pass additional options as expressed in the table 4.1:
load files(:Files)
Equivalent to load files(Files, []). Same as consult/1, See load files/2 for sup-
ported options.
autoload(Bool)
If true (default false), indicate that this load is a demand load. This implies that,
depending on the setting of the Prolog flag verbose autoload, the load action is
printed at level informational or silent. See also print message/2 and
current prolog flag/2.
derived from(File)
Indicate that the loaded file is derived from File. Used by make/0 to time-check and
load the original file rather than the derived file.
dialect(+Dialect)
Load Files with enhanced compatibility with the target Prolog system identified by Di-
alect. See expects dialect/1 and section C for details.
encoding(Encoding)
Specify the way characters are encoded in the file. Default is taken from the Prolog flag
encoding. See section 2.18.1 for details.
expand(Bool)
If true, run the filenames through expand file name/2 and load the returned files.
Default is false, except for consult/1 which is intended for interactive use. Flexible
location of files is defined by file search path/2.
format(+Format)
Used to specify the file format if data is loaded from a stream using the stream(Stream)
option. Default is source, loading Prolog source text. If qlf, load QLF data (see
qcompile/1).
if(Condition)
Load the file only if the specified condition is satisfied. The value true loads the file
unconditionally, changed loads the file if it was not loaded before or has been modified
since it was loaded the last time, and not loaded loads the file if it was not loaded
before.
imports(Import)
Specify what to import from the loaded module. The default for use module/1 is
all. Import is passed from the second argument of use module/2. Traditionally it is
a list of predicate indicators to import. As part of the SWI-Prolog/YAP integration, we
also support Pred as Name to import a predicate under another name. Finally, Import
can be the term except(Exceptions), where Exceptions is a list of predicate indicators
that specify predicates that are not imported or Pred as Name terms to denote renamed
predicates. See also reexport/2 and use module/2.5
If Import equals all, all operators are imported as well. Otherwise, operators are not
imported. Operators can be imported selectively by adding terms op(Pri,Assoc,Name) to
the Import list. If such a term is encountered, all exported operators that unify with this
term are imported. Typically, this construct will be used with all arguments unbound to
import all operators or with only Name bound to import a particular operator.
modified(TimeStamp)
Claim that the source was loaded at TimeStamp without checking the source. This option
is intended to be used together with the stream(Input) option, for example after
extracting the time from an HTTP server or database.
module(+Module)
Load the indicated file into the given module, overruling the module name specified in
the :- module(Name, ...) directive. This currently serves two purposes: (1) allow
5
BUG: Name/Arity as NewName is currently implemented using a link clause. This harms efficiency and does not allow
for querying the relation through predicate property/2.
loading two module files that specify the same module into the same process and force
and (2): force loading source code in a specific module, even if the code provides its own
module name. Experimental.
must be module(Bool)
If true, raise an error if the file is not a module file. Used by use module/[1,2].
qcompile(Atom)
How to deal with quick-load-file compilation by qcompile/1. Values are:
never
Default. Do not use qcompile unless called explicitly.
auto
Use qcompile for all writeable files. See comment below.
large
Use qcompile if the file is large. Currently, files larger than 100 Kbytes are consid-
ered large.
part
If load files/2 appears in a directive of a file that is compiled into Quick Load
Format using qcompile/1, the contents of the argument files are included in the
.qlf file instead of the loading directive.
If this option is not present, it uses the value of the Prolog flag qcompile as default.
redefine module(+Action)
Defines what to do if a file is loaded that provides a module that is already loaded from
another file. Action is one of false (default), which prints an error and refuses to load
the file, or true, which uses unload file/1 on the old file and then proceeds loading
the new file. Finally, there is ask, which starts interaction with the user. ask is only
provided if the stream user input is associated with a terminal.
reexport(Bool)
If true re-export the imported predicate. Used by reexport/1 and reexport/2.
register(Bool)
If false, do not register the load location and options. This option is used by
make/0 and load hotfixes/1 to avoid polluting the load-context database. See
source file property/2.
sandboxed(Bool)
Load the file in sandboxed mode. This option controls the flag sandboxed load. The
only meaningful value for Bool is true. Using false while the Prolog flag is set to
true raises a permission error.
scope settings(Bool)
Scope style check/1 and expects dialect/1 to the file and files loaded from
the file after the directive. Default is true. The system and user initialization files (see
-f and -F) are loading with scope settings(false).
silent(Bool)
If true, load the file without printing a message. The specified value is the default for
all files loaded as a result of loading the specified files. This option writes the Prolog flag
verbose load with the negation of Bool.
stream(Input)
This SWI-Prolog extension compiles the data from the stream Input. If this option is
used, Files must be a single atom which is used to identify the source location of the
loaded clauses as well as to remove all clauses if the data is reconsulted.
This option is added to allow compiling from non-file locations such as databases, the
web, the user (see consult/1) or other servers. It can be combined with format(qlf)
to load QLF data from a stream.
The load files/2 predicate can be hooked to load other data or data from objects other than
files. See prolog load file/2 for a description and http/http load for an example.
All hooks for load files/2 are documented in section B.8.
consult(:File)
Read File as a Prolog source file. Calls to consult/1 may be abbreviated by just typing a
number of filenames in a list. Examples:
ensure loaded(:File)
If the file is not already loaded, this is equivalent to consult/1. Otherwise, if the file defines
a module, import all public predicates. Finally, if the file is already loaded, is not a module
file, and the context module is not the global user module, ensure loaded/1 will call
consult/1.
With this semantics, we hope to get as close as possible to the clear semantics with-
out the presence of a module system. Applications using modules should consider using
use module/[1,2].
Equivalent to load_files(Files, [if(not_loaded)]).6
include(+File) [ISO]
Textually include the content of File at the position where the directive
:- include(File). appears. The include construct is only honoured if it appears
as a directive in a source file. Textual include (similar to C/C++ #include) is obviously useful
for sharing declarations such as dynamic/1 or multifile/1 by including a file with
directives from multiple files that use these predicates.
Textually including files that contain clauses is less obvious. Normally, in SWI-Prolog, clauses
are owned by the file in which they are defined. This information is used to replace the old
6
On older versions the condition used to be if(changed). Poor time management on some machines or copying
often caused problems. The make/0 predicate deals with updating the running system after changing the source code.
definition after the file has been modified and is reloaded by, e.g., make/0. As we understand
it, include/1 is intended to include the same file multiple times. Including a file holding
clauses multiple times into the same module is rather meaningless as it just duplicates the same
clauses. Including a file holding clauses in multiple modules does not suffer from this problem,
but leads to multiple equivalent copies of predicates. Using use module/1 can achieve the
same result while sharing the predicates.
If include/1 is used to load files holding clauses, and if these files are loaded only once,
then these include/1 directives can be replaced by other predicates (such as consult/1).
However, there are several cases where either include/1 has no alternative, or using any
alternative also requires other changes. An example of the former is using include/1 to
share directives. An example of the latter are cases where clauses of different predicates
are distributed over multiple files: If these files are loaded with include/1, the directive
discontiguous/1 is appropriate, whereas if they are consulted, one must use the directive
multifile/1.
To accommodate included files holding clauses, SWI-Prolog distinguishes between the source
location of a clause (in this case the included file) and the owner of a clause (the file that includes
the file holding the clause). The source location is used by, e.g., edit/1, the graphical tracer,
etc., while the owner is used to determine which clauses are removed if the file is modified.
Relevant information is found with the following predicates:
require(+ListOfNameAndArity)
Declare that this file/module requires the specified predicates to be defined with their com-
monly accepted definition. This predicate originates from the Prolog portability layer for
XPCE. It is intended to provide a portable mechanism for specifying that this module requires
the specified predicates.
The implementation normally first verifies whether the predicate is already defined. If not, it
will search the libraries and load the required library.
SWI-Prolog, having autoloading, does not load the library. Instead it creates a procedure header
for the predicate if it does not exist. This will flag the predicate as undefined. See also
check/0 and autoload/0.
encoding(+Encoding)
This directive can appear anywhere in a source file to define how characters are encoded in the
remainder of the file. It can be used in files that are encoded with a superset of US-ASCII,
currently UTF-8 and ISO Latin-1. See also section 2.18.1.
make
Consult all source files that have been changed since they were consulted. It checks all loaded
source files: files loaded into a compiled state using pl -c ... and files loaded using
consult/1 or one of its derivatives. The predicate make/0 is called after edit/1,
automatically reloading all modified files. If the user uses an external editor (in a separate
window), make/0 is normally used to update the program after editing. In addition, make/0
updates the autoload indices (see section 2.13) and runs list undefined/0 from the
check library to report on undefined predicates.
library directory(?Atom)
Dynamic predicate used to specify library directories. Default ./lib, /lib/prolog and
the systems library (in this order) are defined. The user may add library directories using
assertz/1, asserta/1 or remove system defaults using retract/1. Deprecated. New
code should use file search path/2.
file_search_path(demo, /usr/lib/prolog/demo).
user:file_search_path(library, X) :-
library_directory(X).
user:file_search_path(swi, Home) :-
current_prolog_flag(home, Home).
user:file_search_path(foreign, swi(ArchLib)) :-
current_prolog_flag(arch, Arch),
atom_concat(lib/, Arch, ArchLib).
user:file_search_path(foreign, swi(lib)).
user:file_search_path(path, Dir) :-
getenv(PATH, Path),
( current_prolog_flag(windows, true)
-> atomic_list_concat(Dirs, (;), Path)
; atomic_list_concat(Dirs, :, Path)
),
member(Dir, Dirs).
The file search path/2 expansion is used by all loading predicates as well as by
absolute file name/[2,3].
The Prolog flag verbose file search can be set to true to help debugging Prologs
search for files.
user:prolog_file_type(pl, prolog).
user:prolog_file_type(Ext, prolog) :-
current_prolog_flag(associate, Ext),
Ext \== pl.
user:prolog_file_type(qlf, qlf).
user:prolog_file_type(Ext, executable) :-
current_prolog_flag(shared_object_extension, Ext).
Users can add extensions for Prolog source files to avoid conflicts (for example with perl)
as well as to be compatible with another Prolog implementation. We suggest using .pro for
avoiding conflicts with perl. Overriding the system definitions can stop the system from
finding libraries.
source file(?File)
True if File is a loaded Prolog source file. File is the absolute and canonical path to the source
file.
load count(-Count)
Count is the number of times the file have been loaded, i.e., 1 (one) if the file has been
loaded once.
modified(Stamp)
File modification time when File was loaded. This is used by make/0 to find files whose
modification time is different from when it was loaded.
module(Module)
File is a module file that declares the module Module.
number of clauses(Count)
Count is the number of clauses associated with File. Note that clauses loaded from in-
cluded files are counted as part of the main file.
reloading
Present if the file is currently being reloaded.
unload file(+File)
Remove all clauses loaded from File. If File loaded a module, clear the modules export list
and disassociate it from the file. File is a canonical filename or a file indicator that is valid for
load files/2.
This predicate should be used with care. The multithreaded nature of SWI-Prolog makes re-
moving static code unsafe. Attempts to do this should be reserved for development or situations
where the application can guarantee that none of the clauses associated to File are active.
Key Description
directory Directory in which source lives
dialect Compatibility mode. See expects dialect/1.
file Similar to source, but returns the file being included when called while
an include file is being processed
module Module into which file is loaded
reload true if the file is being reloaded. Not present on first load
script Boolean that indicates whether the file is loaded as a script file (see -s)
source File being loaded. If the system is processing an included file, the value
is the main file. Returns the original Prolog file when loading a .qlf
file.
stream Stream identifier (see current input/1)
term position Start position of last term read. See also stream property/2
(position property and stream position data/3.8
term Term being expanded by expand term/2.
variable names A list of Name = Var of the last term read. See read term/2 for
details.
The directory is commonly used to add rules to file search path/2, setting up a
search path for finding files with absolute file name/3. For example:
:- dynamic user:file_search_path/2.
:- multifile user:file_search_path/2.
:- prolog_load_context(directory, Dir),
asserta(user:file_search_path(my_program_home, Dir)).
...
absolute_file_name(my_program_home(README.TXT), ReadMe,
[ access(read) ]),
...
at halt(:Goal)
Register Goal to be run from PL cleanup(), which is called when the system halts. The
hooks are run in the reverse order they were registered (FIFO). Success or failure executing
a hook is ignored. If the hook raises an exception this is printed using print message/2.
An attempt to call halt/[0,1] from a hook is ignored. Hooks may call cancel halt/1,
causing halt/0 and PL halt(0) to print a message indicating that halting the system has
been cancelled.
cancel halt(+Reason)
If this predicate is called from a hook registered with at halt/1, halting Prolog is cancelled
and an informational message is printed that includes Reason. This is used by the development
tools to cancel halting the system if the editor has unsafed data and the user decides to cancel.
:- initialization(:Goal) [ISO]
Call Goal after loading the source file in which this directive appears has been completed. In
addition, Goal is executed if a saved state created using qsave program/1 is restored.
The ISO standard only allows for using :- Term if Term is a directive. This means that
arbitrary goals can only be called from a directive by means of the initialization/1
directive. SWI-Prolog does not enforce this rule.
The initialization/1 directive must be used to do program initialization in saved states
(see qsave program/1). A saved state contains the predicates, Prolog flags and operators
present at the moment the state was created. Other resources (records, foreign resources, etc.)
must be recreated using initialization/1 directives or from the entry goal of the saved
state.
Up to SWI-Prolog 5.7.11, Goal was executed immediately rather than after load-
ing the program text in which the directive appears as dictated by the ISO stan-
dard. In many cases the exact moment of execution is irrelevant, but there are
exceptions. For example, load foreign library/1 must be executed immedi-
ately to make the loaded foreign predicates available for exporting. SWI-Prolog
now provides the directive use foreign library/1 to ensure immediate loading as
well as loading after restoring a saved state. If the system encounters a directive
:- initialization(load foreign library(...)), it will load the foreign li-
brary immediately and issue a warning to update your code. This behaviour can be extended
by providing clauses for the multifile hook predicate prolog:initialize now(Term, Ad-
vice), where Advice is an atom that gives advice on how to resolve the compatibility issue.
initialization(:Goal, +When)
Similar to initialization/1, but allows for specifying when Goal is executed while
loading the program text:
now
Execute Goal immediately.
after load
Execute Goal after loading program text. This is the same as initialization/1.
restore
Do not execute Goal while loading the program, but only when restoring a state.
compiling
True if the system is compiling source files with the -c option or qcompile/1 into
an intermediate code file. Can be used to perform conditional code optimisations in
term expansion/2 (see also the -O option) or to omit execution of directives during
compilation.
de-facto standard. This mechanism can do arbitrary translation between valid Prolog terms read from
the source file to Prolog terms handed to the compiler. As term expansion/2 can return a list,
the transformation does not need to be term-to-term.
Various Prolog dialects provide the analogous goal expansion/2 and expand goal/2 that
allow for translation of individual body terms, freeing the user of the task to disassemble each clause.
When compiling a module (see chapter 6 and the directive module/2), expand term/2
will first try term expansion/2 in the module being compiled to allow for term expan-
sion rules that are local to a module. If there is no local definition, or the local definition
fails to translate the term, expand term/2 will try term expansion/2 in module user.
For compatibility with SICStus and Quintus Prolog, this feature should not be used. See also
expand term/2, goal expansion/2 and expand goal/2.
1. Test conditional compilation directives and translate all input to [] if we are in a false
branch of the conditional compilation. See section 4.3.1.
2. Call term expansion/2. This predicate is first tried in the module that is being com-
piled and then in the module user.
3. Call DCG expansion (dcg translate rule/2).
4. Call expand goal/2 on each body term that appears in the output of the previous steps.
meta-predicate that is annotated using 0 (see meta predicate/1). Other cases need a real
predicate definition.
The expansion hook can use prolog load context/2 to obtain information about the con-
text in which the goal is exanded such as the module, variable names or the encapsulating term.
fresh(Bool)
Bool has the value true if the variable is guaranteed to be unbound at entry of the goal,
otherwise its value is false. This implies that the variable first appears in this goal or a
previous appearance was in a negation (\+/1) or a different branch of a disjunction.
name(Name)
True when variable appears with the given name in the source.
Conditional compilation
Conditional compilation builds on the same principle as term expansion/2,
goal expansion/2 and the expansion of grammar rules to compile sections of the source
code conditionally. One of the reasons for introducing conditional compilation is to simplify writing
portable code. See section C for more information. Here is a simple example:
:- if(\+source_exports(library(lists), suffix/2)).
suffix(Suffix, List) :-
append(_, Suffix, List).
:- endif.
Note that these directives can only appear as separate terms in the input. Typical usage scenarios
include:
:- if(:Goal)
Compile subsequent code only if Goal succeeds. For enhanced portability, Goal is processed
by expand goal/2 before execution. If an error occurs, the error is printed and processing
proceeds as if Goal has failed.
:- elif(:Goal)
Equivalent to :- else. :-if(Goal). ... :- endif. In a sequence as below, the
section below the first matching elif is processed. If no test succeeds, the else branch is
processed.
:- if(test1).
section_1.
:- elif(test2).
section_2.
:- elif(test3).
section_3.
:- else.
section_else.
:- endif.
:- else
Start else branch.
:- endif
End of conditional compilation.
Trace a goal
Find unexpected behaviour of a predicate
Enter a break using the b command
Fix the sources and reload them using make/0
Exit the break, retry executing the now fixed predicate using the r command
Reloading a previously loaded file is safe, both in the debug scenario above and when the code
is being executed by another thread. Executing threads switch atomically to the new definition of
modified predicates, while clauses that belong to the old definition are (eventually) reclaimed by
garbage collect clauses/0.9 Below we describe the steps taken for reloading a file to help
understanding the limitations of the process.
1. If a file is being reloaded, a reload context is associated to the file administration. This context
includes a table keeping track of predicates and a table keeping track of the module(s) associated
with this source.
2. If a new predicate is found, an entry is added to the context predicate table. Three options are
considered:
(a) The predicate is new. It is handled the same as if the file was loaded for the first time.
(b) The predicate is foreign or thread local. These too are threaded as if the file was loaded
for the first time.
(c) Normal predicates. Here we initialise a pointer to the current clause.
(a) If the clauses byte-code is the same as the predicates current clause, discard the clause
and advance the current clause pointer.
(b) If the clauses byte-code is the same as some clause further into the clause list of the
predicate, discard the new clause, mark all intermediate clauses for future deletion, and
advance the current clause pointer to the first clause after the matched one.
(c) If the clauses byte-code matches no clause, insert it for future activation before the current
clause and keep the current clause.
4. Properties such as dynamic or meta predicate are in part applied immediately and
in part during the fixup process after the file completes loading. Currently, dynamic and
thread local are applied immediately.
5. New modules are recorded in the reload context. Export declarations (the modules public list
and export/1 calls) are both applied and recorded.
6. When the end-of-file is reached, the following fixup steps are taken
(a) For each predicate
i. The current clause and subsequent clauses are marked for future deletion.
ii. All clauses marked for future deletion or creation are (in)activated by changing their
erased or created generation. Erased clauses are (eventually) reclaimed by the
clause garbage collector, see garbage collect clauses/0.
iii. Pending predicate property changes are applied.
(b) For each module
i. Exported predicates that are not encountered in the reload context are removed from
the export list.
The above generally ensures that changes to the content of source files can typically be activated
safely using make/0. Global changes such as operator changes, changes of module names, changes
to multi-file predicates, etc. sometimes require a restart. In almost all cases, the need for restart
is indicated by permission or syntax errors during the reload or existence errors while running the
program. If the content of a source file refers to itself there are some additional limitations, which
are listed below. In some cases, loading the file twice establishes the right result. In others one may
use unload file/1 to remove the file before reloading. In some cases, the process needs to be
restarted.
Directives that execute code in the current file will use the old definition of predicates because
the new only become available at the end of the loading process. If the standard required
initialization/1 directive is used there is no problem because the associated goal is
executed after the file completes loading.
Module-local rules for goal expansion/2 or term expansion/2 execute the old defi-
nition. If such rules are changed, they become active after loading the file twice, where the first
reload updates the expansion rules and the second uses them.
Expansion and directives can normally only refer to predicates defined before they are used.
During reload, it is also possible to refer to predicates defined after the location they are used.
This may cause a file to work properly while being reloaded, but failing while being loaded in
a fresh image.
Using goal expansion/2 that calls compile aux clauses/1, assuming that multiple
expansions can use the same auxiliary definition must use predicate property/2 using
the property defined to test whether the definition is already defined in the current context.
Starting with version 5.11.27, the autoloader is no longer locked and multiple threads can compile
files concurrently. This requires special precautions only if multiple threads wish to load the same
file at the same time. Therefore, load files/2 checks automatically whether some other thread is
already loading the file. If not, it starts loading the file. If another thread is already loading the file, the
thread blocks until the other thread finishes loading the file. After waiting, and if the file is a module
file, it will make the public predicates available.
Note that this schema does not prevent deadlocks under all situations. Consider two mutually
dependent (see section 4.3.2) module files A and B, where thread 1 starts loading A and thread 2
starts loading B at the same time. Both threads will deadlock when trying to load the used module.
The current implementation does not detect such cases and the involved threads will freeze. This
problem can be avoided if a mutually dependent collection of files is always loaded from the same
start file.
SWI-Prolog supports compilation of individual or multiple Prolog source files into Quick Load Files.
A Quick Load File (.qlf file) stores the contents of the file in a precompiled format.
These files load considerably faster than source files and are normally more compact. They are
machine-independent and may thus be loaded on any implementation of SWI-Prolog. Note, however,
that clauses are stored as virtual machine instructions. Changes to the compiler will generally make
old compiled files unusable.
Quick Load Files are created using qcompile/1. They are loaded using consult/1 or one
of the other file-loading predicates described in section 4.3. If consult/1 is given an explicit .pl
file, it will load the Prolog source. When given a .qlf file, it will load the file. When no extension is
specified, it will load the .qlf file when present and the .pl file otherwise.
qcompile(:File)
Takes a file specification as consult/1, etc., and, in addition to the normal compilation,
creates a Quick Load File from File. The file extension of this file is .qlf. The basename of
the Quick Load File is the same as the input file.
If the file contains :- consult(+File), :- [+File] or
:- load files(+File, [qcompile(part), ...]) statements, the referred
files are compiled into the same .qlf file. Other directives will be stored in the .qlf file and
executed in the same fashion as when loading the .pl file.
For term expansion/2, the same rules as described in section 2.10 apply.
Conditional execution or optimisation may test the predicate compiling/0.
Source references (source file/2) in the Quick Load File refer to the Prolog source file
from which the compiled code originates.
qcompile(:File, +Options)
As qcompile/1, but processes additional options as defined by load files/2.12
12
BUG: Option processing is currently incomplete.
edit(+Specification)
First, exploit prolog edit:locate/3 to translate Specification into a list of Locations.
If there is more than one hit, the user is asked to select from the locations found. Finally,
prolog edit:edit source/1 is used to invoke the users preferred editor. Typically,
edit/1 can be handed the name of a predicate, module, basename of a file, XPCE class,
XPCE method, etc.
edit
Edit the default file using edit/1. The default file is the file loaded with the command line
option -s or, in Windows, the file loaded by double-clicking from the Windows shell.
multifile predicate is normally not defined. If it succeeds, edit/1 assumes the editor is
started.
If it fails, edit/1 uses its internal defaults, which are defined by the Prolog flag editor
and/or the environment variable EDITOR. The following rules apply. If the Prolog flag
editor is of the format $hnamei, the editor is determined by the environment variable hnamei.
Else, if this flag is pce emacs or built in and XPCE is loaded or can be loaded, the built-in
Emacs clone is used. Else, if the environment EDITOR is set, this editor is used. Finally, vi is
used as default on Unix systems and notepad on Windows.
See the default user preferences file dotfiles/dotswiplrc for examples.
If the editor can deal with starting at a specified line, two clauses should be provided. The first
pattern invokes the editor with a line number, while the second is used if the line number is
unknown.
The default contains definitions for vi, emacs, emacsclient, vim, notepad and
wordpad . Starred editors do not provide starting at a given line number.
Please contribute your specifications to [email protected].
prolog edit:load
Normally an undefined multifile predicate. This predicate may be defined to provide loading
hooks for user extensions to the edit module. For example, XPCE provides the code below to
load swi edit, containing definitions to locate classes and methods as well as to bind this
package to the PceEmacs built-in editor.
:- multifile prolog_edit:load/0.
prolog_edit:load :-
ensure_loaded(library(swi_edit)).
A listing is produced by enumerating the clauses of the predicate using clause/2 and printing
each clause using portray clause/1. This implies that the variable names are generated
(A, B, . . . ) and the layout is defined by rules in portray clause/1.
listing
List all predicates from the calling module using listing/1. For example, ?- listing.
lists clauses in the default user module and ?- lists:listing. lists the clauses in the
module lists.
portray clause(+Clause)
Pretty print a clause. A clause should be specified as a term hHeadi :- hBodyi. Facts are
represented as hHeadi :- true or simply hHeadi. Variables in the clause are written as A,
B, . . . . Singleton variables are written as _. See also portray clause/2.
var(@Term) [ISO]
True if Term currently is a free variable.
nonvar(@Term) [ISO]
True if Term currently is not a free variable.
integer(@Term) [ISO]
True if Term is bound to an integer.
float(@Term) [ISO]
True if Term is bound to a floating point number.
rational(@Term)
True if Term is bound to a rational number. Rational numbers include integers.
number(@Term) [ISO]
True if Term is bound to an integer or floating point number.13
atom(@Term) [ISO]
True if Term is bound to an atom.
13
As rational numbers are not atomic in the current implementation and we do not want to break the rule that number/1
implies atomic/1, number/1 fails on rational numbers. This will change if rational numbers become atomic.
blob(@Term, ?Type)
True if Term is a blob of type Type. See section 11.4.7.
string(@Term)
True if Term is bound to a string. Note that string here refers to the built-in atomic type string as
described in section 5.2. Starting with version 7, the syntax for a string object is text between
double quotes, such as "hello".14 See also the Prolog flag double quotes.
atomic(@Term) [ISO]
True if Term is bound (i.e., not a variable) and is not compound. Thus, atomic acts as if defined
by:
atomic(Term) :-
nonvar(Term),
\+ compound(Term).
SWI-Prolog defines the following atomic datatypes: atom (atom/1), string (string/1), in-
teger (integer/1), floating point number (float/1) and blob (blob/2). In addition, the
symbol [] (empty list) is atomic, but not an atom. See section 5.1.
compound(@Term) [ISO]
True if Term is bound to a compound term. See also functor/3 =../2,
compound name arity/3 and compound name arguments/3.
callable(@Term) [ISO]
True if Term is bound to an atom or a compound term. This was intended as a type-test for
arguments to call/1 and call/2.. Note that callable only tests the surface term. Terms
such as (22,true) are considered callable, but cause call/1 to raise a type error. Module-
qualification of meta-argument (see meta predicate/1) using :/2 causes callable to
succeed on any meta-argument.15 Consider the program and query below:
:- meta_predicate p(0).
?- p(22).
ERROR: Type error: callable expected, found 22
ERROR: In:
ERROR: [6] p(user:22)
ground(@Term) [ISO]
True if Term holds no free variables.
14
In traditional Prolog systems, double quoted text is often mapped to a list of character codes.
15
We think that callable/1 should be deprecated and there should be two new predicates, one performing a test for
callable that is minimally module aware and possibly consistent with type-checking in call/1 and a second predicate that
tests for atom or compound.
cyclic term(@Term)
True if Term contains cycles, i.e. is an infinite term. See also acyclic term/1 and sec-
tion 2.16.16
=(Term, Term).
1. Variables < Numbers < Strings < Atoms < Compound Terms
2. Variables are sorted by address. Attaching attributes (see section 7.1) does not affect the order-
ing.
3. Numbers are compared by value. Mixed integer/float are compared as floats. If the comparison
is equal, the float is considered the smaller value. If the Prolog flag iso is defined, all floating
point numbers precede all integers.
6. Compound terms are first checked on their arity, then on their functor name (alphabetically) and
finally recursively on their arguments, leftmost argument first.
1 ?- A = f(A).
A = f(A).
2 ?- unify_with_occurs_check(A, f(A)).
false.
The first statement creates a cyclic term, also called a rational tree. The second executes log-
ically sound unification and thus fails. Note that the behaviour of unification through =/2 as
well as implicit unification in the head can be changed using the Prolog flag occurs check.
The SWI-Prolog implementation of unify with occurs check/2 is cycle-safe and only
guards against creating cycles, not against cycles that may already be present in one of the
arguments. This is illustrated in the following two queries:
Some other Prolog systems interpret unify with occurs check/2 as if defined by the
clause below, causing failure on the above two queries. Direct use of acyclic term/1 is
portable and more appropriate for such applications.
unify_with_occurs_check(X,X) :- acyclic_term(X).
1 a =@= A false
2 A =@= B true
3 x(A,A) =@= x(B,C) false
4 x(A,A) =@= x(B,B) true
5 x(A,A) =@= x(A,B) false
6 x(A,B) =@= x(C,D) true
7 x(A,B) =@= x(B,A) true
8 x(A,B) =@= x(C,A) true
A term is always a variant of a copy of itself. Term copying takes place in, e.g., copy term/2,
findall/3 or proving a clause added with asserta/1. In the pure Prolog world (i.e.,
without attributed variables), =@=/2 behaves as if defined below. With attributed variables,
variant of the attributes is tested rather than trying to satisfy the constraints.
A =@= B :-
copy_term(A, Ac),
copy_term(B, Bc),
numbervars(Ac, 0, N),
numbervars(Bc, 0, N),
Ac == Bc.
The SWI-Prolog implementation is cycle-safe and can deal with variables that are shared be-
tween the left and right argument. Its performance is comparable to ==/2, both on success and
(early) failure. 18
17
Row 7 and 8 of this table may come as a surprise, but row 8 is satisfied by (left-to-right) A C, B A and (right-
to-left) C A, A B. If the same variable appears in different locations in the left and right term, the variant relation
can be broken by consistent binding of both terms. E.g., after binding the first argument in row 8 to a value, both terms are
no longer variant.
18
The current implementation is contributed by Kuniaki Mukai.
This predicate is known by the name variant/2 in some other Prolog systems. Be aware
of possible differences in semantics if the arguments contain attributed variables or share vari-
ables.19
?=(@Term1, @Term2)
Succeeds if the syntactic equality of Term1 and Term2 can be decided safely, i.e. if the result of
Term1 == Term2 will not change due to further instantiation of either term. It behaves as if
defined by ?=(X,Y) :- \+ unifiable(X,Y,[_|_]).
one_character_atoms(As) :-
findall(A, (current_atom(A), atom_length(A, 1)), As).
fail [ISO]
Always fail. The predicate fail/0 is translated into a single virtual machine instruction.
false [ISO]
Same as fail, but the name has a more declarative connotation.
19
In many systems variant is implemented using two calls to subsumes term/2.
20
This predicate is often named subsumes chk/2 in older Prolog dialects. The current name was established in the ISO
WG17 meeting in Edinburgh (2010). The chk postfix was considered to refer to determinism as in e.g., memberchk/2.
21
This predicate was introduced for the implementation of dif/2 and when/2 after discussion with Tom Schrijvers and
Bart Demoen. None of us is really happy with the name and therefore suggestions for a new name are welcome.
true [ISO]
Always succeed. The predicate true/0 is translated into a single virtual machine instruction.
repeat [ISO]
Always succeed, provide an infinite number of choice points.
! [ISO]
Cut. Discard all choice points created since entering the predicate in which the cut appears.
In other words, commit to the clause in which the cut appears and discard choice points that
have been created by goals to the left of the cut in the current clause. Meta calling is opaque to
the cut. This implies that cuts that appear in a term that is subject to meta-calling (call/1)
only affect choice points created by the meta-called term. The following control structures are
transparent to the cut: ;/2, ->/2 and *->/2. Cuts appearing in the condition part of ->/2
and *->/2 are opaque to the cut. The table below explains the scope of the cut with examples.
Prunes here means prunes X choice point created by X.
:Goal1 | :Goal2
Equivalent to ;/2. Retained for compatibility only. New code should use ;/2.
Please note that (If -> Then) acts as (If -> Then ; fail), making the construct fail if the condition
fails. This unusual semantics is part of the ISO and all de-facto Prolog standards.
Please note that (if->then;else) is read as ((if->then);else) and that the combined semantics
of this syntactic construct as defined above is different from the simple nesting of the two
individual constructs, i.e., the semantics of ->/2 changes when embedded in ;/2. See also
once/1.
optional(Goal) :-
( Goal
*-> true
; true
).
\+ :Goal [ISO]
True if Goal cannot be proven (mnemonic: + refers to provable and the backslash (\) is
normally used to indicate negation in Prolog).
call(:Goal) [ISO]
Invoke Goal as a goal. Note that clauses may have variables as subclauses, which is identical
to call/1.
22
BUG: The decompiler implemented by clause/2 returns this construct as a normal conjunction too.
apply(:Goal, +List)
Append the members of List to the arguments of Goal and call the resulting term. For example:
apply(plus(1), [2, X]) calls plus(1, 2, X). New code should use call/[2..] if
the length of List is fixed.
not(:Goal)
True if Goal cannot be proven. Retained for compatibility only. New code should use \+/1.
once(:Goal) [ISO]
Make a possibly nondet goal semidet, i.e., succeed at most once. Defined as:
once(Goal) :-
call(Goal), !.
once/1 can in many cases be replaced with ->/2. The only difference is how the cut behaves
(see !/0). The following two clauses below are identical. Be careful about the interaction with
;/2. The apply macros library defines an inline expansion of once/1, mapping it to
(Goal\send{true};fail). Using the full if-then-else constructs prevents its semantics
from being changed when embedded in a ;/2 disjunction.
1) a :- once((b, c)), d.
2) a :- b, c -> d.
ignore(:Goal)
Calls Goal as once/1, but succeeds, regardless of whether Goal succeeded or not. Defined as:
ignore(Goal) :-
Goal, !.
ignore(_).
limit was exceeded during the proof, or the entire predicate fails if Goal fails without exceeding
Limit.
The depth limit is guarded by the internal machinery. This may differ from the depth computed
based on a theoretical model. For example, true/0 is translated into an inline virtual machine
instruction. Also, repeat/0 is not implemented as below, but as a non-deterministic foreign
predicate.
repeat.
repeat :-
repeat.
As a result, call with depth limit/3 may still loop infinitely on programs that should
theoretically finish in finite time. This problem can be cured by using Prolog equivalents to
such built-in predicates.
This predicate may be used for theorem provers to realise techniques like iterative deepen-
ing. See also call with inference limit/3. It was implemented after discussion with
Steve Moyle [email protected].
If Goal does not terminate before the inference limit is exceeded, Goal is aborted by inject-
ing the exception inference limit exceeded into its execution. After termination
of Goal, Result is unified with the atom inference limit exceeded. Otherwise,
If Goal fails, call with inference limit/3 fails.
If Goal succeeds without a choice point, Result is unified with !.
If Goal succeeds with a choice point, Result is unified with true.
If Goal throws an exception, call with inference limit/3 re-throws the excep-
tion.
An inference is defined as a call or redo on a predicate. Please note that some primitive built-in
predicates are compiled to virtual machine instructions for which inferences are not counted.
The execution of predicates defined in other languages (e.g., C, C++) count as a single inference.
This includes potentially expensive built-in predicates such as sort/2.
Calls to this predicate may be nested. An inner call that sets the limit below the current is
honoured. An inner call that would terminate after the current limit does not change the effective
limit. See also call with depth limit/3 and call with time limit/2.
(package clib) or thread signal/2. In most uses, Setup will perform temporary
side-effects required by Goal that are finally undone by Cleanup.
Success or failure of Cleanup is ignored, and choice points it created are destroyed (as
once/1). If Cleanup throws an exception, this is executed as normal.26
Typically, this predicate is used to cleanup permanent data storage required to execute Goal,
close file descriptors, etc. The example below provides a non-deterministic search for a term in
a file, closing the stream as needed.
term_in_file(Term, File) :-
setup_call_cleanup(open(File, read, In),
term_in_stream(Term, In),
close(In) ).
term_in_stream(Term, In) :-
repeat,
read(In, T),
( T == end_of_file
-> !, fail
; T = Term
).
Note that it is impossible to implement this predicate in Prolog. The closest approxima-
tion would be to read all terms into a list, close the file and call member/2. With-
out setup call cleanup/3 there is no way to gain control if the choice point left by
repeat/0 is removed by a cut or an exception.
setup call cleanup/3 can also be used to test determinism of a goal, providing a portable
alternative to deterministic/1:
?- setup_call_cleanup(true,(X=1;X=2), Det=yes).
X = 1 ;
X = 2,
Det = yes ;
This predicate is under consideration for inclusion into the ISO standard. For compatibility with
other Prolog implementations see call cleanup/2.
setup call catcher cleanup(:Setup, :Goal, +Catcher, :Cleanup)
Similar to setup call cleanup(Setup, Goal, Cleanup) with additional information on the
reason for calling Cleanup. Prior to calling Cleanup, Catcher unifies with the termination code
(see below). If this unification fails, Cleanup is not called.
exit
Goal succeeded without leaving any choice points.
26
BUG: During the execution of Cleanup, garbage collection and stack-shifts are disabled.
fail
Goal failed.
!
Goal succeeded with choice points and these are now discarded by the execution of a cut
(or other pruning of the search tree such as if-then-else).
exception(Exception)
Goal raised the given Exception.
external exception(Exception)
Goal succeeded with choice points and these are now discarded due to an exception. For
example:
?- setup_call_catcher_cleanup(true, (X=1;X=2),
Catcher, writeln(Catcher)),
throw(ball).
external_exception(ball)
ERROR: Unhandled exception: Unknown message: ball
shift(+Ball)
Abandon the execution of the current goal, returning control to just after the matching
reset/3 call. This is similar to throw/1 except that (1) nothing is undone and (2) the
3th argument of reset/3 is unified with the continuation, which allows the code calling
reset/3 to resume the current goal.
throw(+Exception) [ISO]
Raise an exception. The system looks for the innermost catch/3 ancestor for which Excep-
tion unifies with the Catcher argument of the catch/3 call. See catch/3 for details.
ISO demands that throw/1 make a copy of Exception, walk up the stack to a catch/3 call,
backtrack and try to unify the copy of Exception with Catcher. SWI-Prolog delays backtrack-
ing until it actually finds a matching catch/3 goal. The advantage is that we can start the
debugger at the first possible location while preserving the entire exception context if there is
no matching catch/3 goal. This approach can lead to different behaviour if Goal and Catcher
of catch/3 call shared variables. We assume this to be highly unlikely and could not think of
a scenario where this is useful.28
In addition to explicit calls to throw/1, many built-in predicates throw exceptions directly
from C. If the Exception term cannot be copied due to lack of stack space, the following actions
are tried in order:
If an exception is raised in a call-back from C (see chapter 11) and not caught in the same
call-back, PL next solution() fails and the exception context can be retrieved using
PL exception().
28
Id like to acknowledge Bart Demoen for his clarifications on these matters.
While looking for the context in which an exception takes place, it is advised to switch on debug
mode using the predicate debug/0. The hook prolog exception hook/4 can be used to add
more debugging facilities to exceptions. An example is the library http/http error, generating
a full stack trace on errors in the HTTP server library.
...,
catch(Goal, E,
( print_message(error, E),
fail
)),
...
Another common use is to define message hook/3 for printing messages that are normally silent,
suppressing messages, redirecting messages or make something happen in addition to printing the
message.
banner
The system banner message. Banner messages can be suppressed by setting the Prolog
flag verbose to silent.
debug(Topic)
Message from library(debug). See debug/3.
error
The message indicates an erroneous situation. This kind is used to print uncaught excep-
tions of type error(Formal, Context). See section introduction (section 4.11.3).
help
User requested help message, for example after entering h or ? to a prompt.
information
Information that is requested by the user. An example is statistics/0.
informational
Typically messages of events are progres that are considered useful to a developer. Such
messages can be suppressed by setting the Prolog flag verbose to silent.
silent
Message that is normally not printed. Applications may define message hook/3 to act
upon such messages.
trace
Messages from the (command line) tracer.
warning
The message indicates something dubious that is not considered fatal. For example,
discontiguous predicates (see discontiguous/1).
The predicate print message/2 first translates the Term into a list of message lines (see
print message lines/3 for details). Next, it calls the hook message hook/3 to allow
the user to intercept the message. If message hook/3 fails it prints the message unless Kind
is silent.
The print message/2 predicate and its rules are in the file
hplhomei/boot/messages.pl, which may be inspected for more information on the
error messages and related error terms. If you need to write messages from your own
predicates, it is recommended to reuse the existing message terms if applicable. If no existing
message term is applicable, invent a fairly unique term that represents the event and define a
rule for the multifile predicate prolog:message//1. See section 4.11.3 for a deeper discussion
and examples.
See also message to string/2.
hFormati-hArgsi
Where Format is an atom and Args is a list of format arguments. Handed to format/3.
flush
If this appears as the last element, Stream is flushed (see flush output/1) and no
final newline is generated. This is combined with a subsequent message that starts with
at same line to complete the line.
at same line
If this appears as first element, no prefix is printed for the first line and the line position is
not forced to 0 (see format/1, N).
ansi(+Attributes, +Format, +Args)
This message may be intercepted by means of the hook prolog:message line element/2.
The library ansi term implements this hook to achieve coloured output. If it is not
intercepted it invokes format(Stream, Format, Args).
nl
A new line is started. If the message is not complete, Prefix is printed before the remainder
of the message.
begin(Kind, Var)
end(Var)
The entire message is headed by begin(Kind, Var) and ended by end(Var). This feature
is used by, e.g., library ansi term to colour entire messages.
hFormati
Handed to format/3 as format(Stream, Format, []). Deprecated because it is am-
biguous if Format collides with one of the atomic commands.
print message/2. Term and Kind are the same as passed to print message/2. Lines
is a list of format statements as described with print message lines/3. See also
message to string/2.
This predicate must be defined dynamic and multifile to allow other modules defining clauses
for it too.
color(-Attributes)
Print message using ANSI terminal attributes. See ansi format/3 for details. Here is
an example, printing help messages in blue:
:- multifile user:message_property/2.
user:message_property(help, color([fg(blue)])).
prefix(-Prefix)
Prefix printed before each line. This argument is handed to format/3. The default is
N. For example, messages of kind warning use NWarning: .
location prefix(+Location, -FirstPrefix, -ContinuePrefix)
Used for printing messages that are related to a source location. Currently, Location is a
term File:Line. FirstPrefix is the prefix for the first line and -ContinuePrefix is the prefix
for continuation lines. For example, the default for errors is
location_prefix(File:Line,
NERROR: w:d:-[File,Line], N\t)).
stream(-Stream)
Stream to which to print the message. Default is user error.
wait(-Seconds)
Amount of time to wait after printing the message. Default is not to wait.
version
Write the SWI-Prolog banner message as well as additional messages registered using
version/1. This is the default initialization goal which can be modified using -g.
version(+Message)
Register additional messages to be printed by version/0. Each registered message is handed
to the message translation DCG and can thus be defined using the hook prolog:message//1. If
not defined, it is simply printed.
download_urls(List) :-
length(List, Total),
forall(nth1(I, List, URL),
( download_url(URL),
print_message(informational,
download_url(URL, I, Total)))).
The programmer can now specify the default textual output using the rule below. Note that this
rule may be in the same file or anywhere else. Notably, the application may come with several rule
sets for different languages. This, and the user-hook example below are the reason to represent the
message as a compound term rather than a string. This is similar to using message numbers in non-
symbolic languages. The documentation of print message lines/3 describes the elements that
may appear in the output list.
:- multifile
prolog:message//1.
A user of the library may define rules for message hook/3. The rule below acts on the message
content. Other applications can act on the message level and, for example, popup a message box for
warnings and errors.
:- multifile user:message_hook/3.
In addition, using the command line option -q, the user can disable all informational messages.
The signal names are defined by the POSIX standard as symbols of the form SIGSIGNAME.
The Prolog name for a signal is the lowercase version of SIGNAME. The predicate
current signal/3 may be used to map between names and signals.
Initially, some signals are mapped to throw, while all other signals are default. The fol-
lowing signals throw an exception: fpe, alrm, xcpu, xfsz and vtalrm.
Portability
On MS-Windows, the signal interface is severely limited. Different Unix brands support differ-
ent sets of signals, and the relation between signal name and number may vary. Currently, the
system only supports signals numbered 1 to 3229 . Installing a signal outside the limited set of
supported signals in MS-Windows crashes the application.
Safety
Immediately delivered signals (see below) are unsafe. This implies that foreign functions called
from a handler cannot safely use the SWI-Prolog API and cannot use C longjmp(). Handlers
defined as throw are unsafe. Handlers defined to call a predicate are safe. Note that the
predicate can call throw/1, but the delivery is delayed until Prolog is in a safe state.
The C-interface described in section 11.4.13 provides the option PL SIGSYNC to select either
safe synchronous or unsafe asynchronous delivery.
Time of delivery
Using throw or a foreign handler, signals are delivered immediately (as defined by the OS).
When using a Prolog predicate, delivery is delayed to a safe moment. Blocking system
calls or foreign loops may cause long delays. Foreign code can improve on that by calling
PL handle signals().
Signals are blocked when the garbage collector is active.
integer(I) -->
digit(D0),
29
TBD: the system should support the Unix realtime signals
digits(D),
{ number_codes(I, [D0|D])
}.
digits([D|T]) -->
digit(D), !,
digits(T).
digits([]) -->
[].
digit(D) -->
[D],
{ code_type(D, digit)
}.
Grammar rule sets are called using the built-in predicates phrase/2 and phrase/3:
phrase(:DCGBody, ?List)
Equivalent to phrase(DCGBody, InputList, []).
?- [library(dcg/basics)].
?- atom_codes(42 times, Codes),
phrase(integer(X), Codes, Rest).
X = 42
Rest = [32, 116, 105, 109, 101, 115]
The next example exploits a complete body. Given the following definition of
digit weight//1, we can pose the query below.
digit_weight(W) -->
[D],
{ code_type(D, digit(W)) }.
Major = 3,
Minor = 4.
The SWI-Prolog implementation of phrase/3 verifies that the List and Rest arguments are
unbound, bound to the empty list or a list cons cell. Other values raise a type error.30 The
predicate call dcg/3 is provided to use grammar rules with terms that are not lists.
Note that the syntax for lists of codes changed in SWI-Prolog version 7 (see section 5.2). If a
DCG body is translated, both "text" and text is a valid code-list literal in version 7. A
version 7 string ("text") is not acceptable for the second and third arguments of phrase/3.
This is typically not a problem for applications as the input of a DCG rarely appears in the
source code. For testing in the toplevel, one must use double quoted text in versions prior to 7
and back quoted text in version 7 or later.
See also portray text/1, which can be used to print lists of character codes as a string to the
top level and debugger to facilitate debugging DCGs that process character codes. The library
apply macros compiles phrase/3 if the argument is sufficiently instantiated, eliminating
the runtime overhead of translating DCGBody and meta-calling.
As stated above, grammar rules are a general interface to difference lists. To illustrate, we show a
DCG-based implementation of reverse/2:
reverse(List, Reversed) :-
phrase(reverse(List), Reversed).
30
The ISO standard allows for both raising a type error and accepting any term as input and output. Note the tail of the
list is not checked for performance reasons.
31
After discussion with Samer Abdallah.
32
This solution was proposed by Markus Triska.
4.14 Database
SWI-Prolog offers several ways to store data in globally accessible memory, i.e., outside the Prolog
stacks. Data stored this way notably does not change on backtracking. Typically it is a bad idea to use
any of the predicates in this section for realising global variables that can be assigned to. Typically,
first consider representing data processed by your program as terms passed around as predicate argu-
ments. If you need to reason over multiple solutions to a goal, consider findall/3, aggregate/3
and related predicates.
Nevertheless, there are scenarios where storing data outside the Prolog stacks is a good option.
Below are the main options for storing data:
Using dynamic predicates Dynamic predicates are predicates for which the list of clauses is mod-
ified at runtime using asserta/1, assertz/1, retract/1 or retractall/1. Fol-
lowing the ISO standard, predicates that are modified this way need to be declared using
the dynamic/1 directive. These facilities are defined by the ISO standard and widely sup-
ported. The mechanism is often considered slow in the literature. Performance depends
on the Prolog implementation. In SWI-Prolog, querying dynamic predicates has the same
performance as static ones. The manipulation predicates are fast. Using retract/1 or
retractall/1 on a predicate registers the predicate as dirty. Dirty predicates are cleaned
by garbage collect clauses/0, which is normally automatically invoked. Some work-
loads may result in significant performance reduction due to skipping retracted clauses and/or
clause garbage collection.
Dynamic predicates can be wrapped using library persistency to maintain a backup of the
data on disk. Dynamic predicates come in two flavours, shared between threads and local to
each thread. The latter version is created using the directive thread local/1.
The recorded database The recorded database registers a list of terms with a key, an atom or com-
pound term. The list is managed using recorda/3, recordz/3 and erase/1. It is queried
using recorded/3. The recorded database is not part of the ISO standard but fairly widely
supported, notably in implementations building on the Edinburgh tradition. There are few
reasons to use this database in SWI-Prolog due to the good performance of dynamic predicates.
Advantages are (1) the handle provides a direct reference to a term, (2) cyclic terms can be
stored and (3) attributes (section 7.1) are preserved. Disadvantages are (1) the terms in a list
associated with a key are not indexed, (2) the poorly specified immediate update semantics (see
section 4.14.5 applies to the recorded database and (3) reduced portability.
The flag/3 predicate The predicate flag/3 associates one simple value (number or atom) with
a key (atom, integer or compound). It is an old SWI-Prolog specific predicate that should be
considered deprecated, although there is no plan to remove it.
Using global variables The predicates b setval/2 and nb setval/2 associate a term living
on the Prolog stack with a name, either backtrackable or non-backtrackable. Backtrack-
able and non-backtrackable assignment without using a global name can be realised with
setarg/3 and nb setarg/3. Notably the latter are used to realise aggregation as e.g.,
aggregate all/3 performs.
Tries As of version 7.3.21, SWI-Prolog provides tries (prefix trees) to associate a term variant with
a value. Tries have been introduced to support tabling and are described in section 4.14.4.
abolish(+Name, +Arity)
Same as abolish(Name/Arity). The predicate abolish/2 conforms to the Edinburgh
standard, while abolish/1 is ISO compliant.
copy_predicate_clauses(From, To) :-
head(From, MF:FromHead),
head(To, MT:ToHead),
FromHead =.. [_|Args],
ToHead =.. [_|Args],
forall(clause(MF:FromHead, Body),
assertz(MT:ToHead, Body)).
head(From, M:Head) :-
strip_module(From, M, Name/Arity),
functor(Head, Name, Arity).
retract(+Term) [ISO,nondet]
When Term is an atom or a term it is unified with the first unifying fact or clause in the database.
The fact or clause is removed from the database. The retract/1 predicate respects the
logical update view. This implies that retract/1 succeeds for all clauses that match Term
when the predicate was called. The example below illustrates that the first call to retract/1
succeeds on bee on backtracking despite the fact that bee is already retracted.33 .
:- dynamic insect/1.
insect(ant).
insect(bee).
?- ( retract(insect(I)),
writeln(I),
retract(insect(bee)),
fail
; true
).
ant ;
bee.
If multiple threads start a retract on the same predicate at the same time their notion of the entry
generation is adjusted such that they do not retract the same first clause. This implies that, if
multiple threads use once(retract(Term)), no two threads will retract the same clause.
Note that on backtracking over retract/1, multiple threads may retract the same clause as
both threads respect the logical update view.
retractall(+Head) [ISO,det]
All facts or clauses in the database for which the head unifies with Head are removed. If Head
refers to a predicate that is not defined, it is implicitly created as a dynamic predicate. See also
dynamic/1.34
asserta(+Term) [ISO]
Assert a fact or clause in the database. Term is asserted as the first fact or clause of the corre-
sponding predicate. Equivalent to assert/1, but Term is asserted as first clause or fact of
the predicate. If the program space for the target module is limited (see set module/1),
asserta/1 can raise a resource error(program space).
assertz(+Term) [ISO]
Equivalent to asserta/1, but Term is asserted as the last clause or fact of the predicate.
assert(+Term)
Equivalent to assertz/1. Deprecated: new code should use assertz/1.
asserta(+Term, -Reference)
Asserts a clause as asserta/1 and unifies Reference with a handle to this clause. The handle
can be used to access this specific clause using clause/3 and erase/1.
assertz(+Term, -Reference)
Equivalent to asserta/1, asserting the new clause as the last clause of the predicate.
33
Example by Jan Burse
34
The ISO standard only allows using dynamic/1 as a directive.
assert(+Term, -Reference)
Equivalent to assertz/2. Deprecated: new code should use assertz/2.
recorda(+Key, +Term)
Equivalent to recorda(Key, Term, ).
recordz(+Key, +Term)
Equivalent to recordz(Key, Term, ).
current_key(Key),
recorded(Key, Value, Reference)
recorded(+Key, -Value)
Equivalent to recorded(Key, Value, ).
erase(+Reference)
Erase a record or clause from the database. Reference is a db-reference returned by
recorda/3, recordz/3 or recorded/3, clause/3, assert/2, asserta/2 or
assertz/2. Fail silently if the referenced object no longer exists. Notably, if multiple
threads attempt to erase the same clause one will succeed and the others will fail.
instance(+Reference, -Term)
Unify Term with the referenced clause or database record. Unit clauses are represented as Head
:- true.
4.14.3 Flags
The predicate flag/3 is the oldest way to store global non-backtrackable data in SWI-Prolog. Flags
are global and shared by all threads. Their value is limited to atoms, small (64-bit) integers and floating
35
Note that, without a given Key, some implementations return triples in the order defined by recorda/2 and
recordz/2.
point numbers. Flags are thread-safe. The flags described in this section must not be confused with
Prolog flags described in section 2.11.
next_id(Id) :-
flag(my_id, Id, Id+1).
4.14.4 Tries
Tries (also called digital tree, radix tree or prefix tree maintain a mapping between a variant of a
term (see =@=/2) and a value. They have been introduced in SWI-Prolog 7.3.21 as part of the
implementation of tabling. The current implementation is rather immature. In particular, the following
limitations currently apply:
We give the definition of these predicates for reference and debugging tabled predicates.
Future versions are likely to get a more stable and safer implementation. The API to tries
should not be considered stable.
trie new(-Trie)
Create a new trie and unify Trie with a handle to the trie. The trie handle is a blob. Tries are
subject to atom garbage collection.
trie destroy(+Trie)
Destroy Trie. This removes all nodes from the trie and causes further access to Trie to raise an
existence error exception. The handle itself is reclaimed by atom garbage collection.
value count(-Count)
Number of key-value pairs in the trie.
node count(-Count)
Number of nodes in the trie.
size(-Bytes)
Required storage space of the trie.
hashed(-Count)
Number of nodes that use a hashed index to its children.
the generation it was created in as well as the generation it was erased from. Only clauses with a
created . . . erased interval that encloses the generation of the current goal are considered visible.
:- dynamic
foo/0,
baz/2.
In SWI-Prolog all these directives are just predicates. This implies they can also be called by a pro-
gram. Do not rely on this feature if you want to maintain portability to other Prolog implementations.
declaration can be queried using predicate property/2. The public/1 directive does
not export the predicate (see module/1 and export/1). The public directive is used for
(1) direct calls into the module from, e.g., foreign code, (2) direct calls into the module from
other modules, or (3) flag a predicate as being called if the call is generated by meta-calling
constructs that are not analysed by the cross-referencer.
current flag(-FlagKey)
Successively unifies FlagKey with all keys used for flags (see flag/3).
current key(-Key)
Successively unifies Key with all keys used for records (see recorda/3, etc.).
call_if_exists(G) :-
current_predicate(_, G),
call(G).
Because of this intended usage, current predicate/2 also succeeds if the predicate can
be autoloaded. Unfortunately, checking the autoloader makes this predicate relatively slow, in
particular because a failed lookup of the autoloader will cause the autoloader to verify that its
index is up-to-date.
predicate property(:Head, ?Property)
True when Head refers to a predicate that has property Property. With sufficiently instan-
tiated Head, predicate property/2 tries to resolve the predicate the same way
as calling it would do: if the predicate is not defined it scans the default modules (see
default module/2) and finally tries the autoloader. Unlike calling, failure to find the
target predicate causes predicate property/2 to fail silently. If Head is not sufficiently
bound, only currently locally defined and already imported predicates are enumerated.
See current predicate/1 for enumerating all predicates. A common issue concerns
generating all built-in predicates. This can be achieved using the code below:
generate_built_in(Name/Arity) :-
predicate_property(system:Head, built_in),
functor(Head, Name, Arity),
\+ sub_atom(Name, 0, _, _, $). % discard reserved names
autoload(File)
True if the predicate can be autoloaded from the file File. Like undefined, this property
is not generated.
built in
True if the predicate is locked as a built-in predicate. This implies it cannot be redefined
in its definition module and it can normally not be seen in the tracer.
defined
True if the predicate is defined. This property is aware of sources being reloaded, in
which case it claims the predicate defined only if it is defined in another source or it has
seen a definition in the current source. See compile aux clauses/1.
dynamic
True if assert/1 and retract/1 may be used to modify the predicate. This property
is set using dynamic/1.
exported
True if the predicate is in the public list of the context module.
imported from(Module)
Is true if the predicate is imported into the context module from module Module.
file(FileName)
Unify FileName with the name of the source file in which the predicate is defined. See
also source file/2 and the property line count. Note that this reports the
file of the first clause of a predicate. A more robust interface can be achieved using
nth clause/3 and clause property/2.
foreign
True if the predicate is defined in the C language.
implementation module(-Module)
True when Module is the module in which Head is or will be defined. Resolving this
property goes through the same search mechanism as when the an undefined predicate is
encountered, but does not perform any loading. It searches (1) the module inheritence
hierarchy (see default module/2) and (2) the autoload index if the unknown flag is
not set to fail in the target module.
indexed(Indexes)
Indexes43 is a list of additional (hash) indexes on the predicate. Each element of the list
is a term ArgSpec-Index. Currently ArgSpec is an integer denoting the argument position
and Index is a term hash(Buckets, Speedup, IsList). Here Buckets is the number of
buckets in the hash and Speedup is the expected speedup relative to trying all clauses
linearly. IsList indicates that a list is created for all clauses with the same key. This is
currently not used.
interpreted
True if the predicate is defined in Prolog. We return true on this because, although the
code is actually compiled, it is completely transparent, just like interpreted code.
iso
True if the predicate is covered by the ISO standard (ISO/IEC 13211-1).
line count(LineNumber)
Unify LineNumber with the line number of the first clause of the predicate. Fails if the
predicate is not associated with a file. See also source file/2. See also the file
property above, notably the reference to clause property/2.
multifile
True if there may be multiple (or no) files providing clauses for the predicate. This
property is set using multifile/1.
meta predicate(Head)
If the predicate is declared as a meta-predicate using meta predicate/1, unify Head
with the head-pattern. The head-pattern is a compound term with the same name and
arity as the predicate where each argument of the term is a meta-predicate specifier. See
meta predicate/1 for details.
nodebug
Details of the predicate are not shown by the debugger. This is the default for built-
in predicates. User predicates can be compiled this way using the Prolog flag
generate debug info.
notrace
Do not show ports of this predicate in the debugger.
number of clauses(ClauseCount)
Unify ClauseCount to the number of clauses associated with the predicate. Fails for
foreign predicates.
number of rules(RuleCount)
Unify RuleCount to the number of clauses associated with the predicate. A rule is defined
as a clauses that has a body that is not just true (i.e., a fact). Fails for foreign
43
This predicate property should be used for analysis and statistics only. The exact representation of Indexes may change
between versions.
predicates. This property is used to avoid analysing predicates with only facts in
prolog codewalk.
public
Predicate is declared public using public/1. Note that without further definition,
public predicates are considered undefined and this property is not reported.
quasi quotation syntax
The predicate (with arity 4) is declared to provide quasi quotation syntax with
quasi quotation syntax/1.
static
The definition can not be modified using assertz/1 and friends. This property is the
opposite from dynamic, i.e., for each defined predicate, either static or dynamic is
true but never both.
thread local
If true (only possible on the multithreaded version) each thread has its own clauses for
the predicate. This property is set using thread local/1.
transparent
True if the predicate is declared transparent using the module transparent/1
or meta predicate/1 declaration. In the latter case the property
meta predicate(Head) is also provided. See chapter 6 for details.
undefined
True if a procedure definition block for the predicate exists, but there are no clauses for
it and it is not declared dynamic or multifile. This is true if the predicate occurs in the
body of a loaded predicate, an attempt to call it has been made via one of the meta-call
predicates, the predicate has been declared as e.g., a meta-predicate or the predicate had
a definition in the past. Originally used to find missing predicate definitions. The current
implementation of list undefined/0 used cross-referencing. Deprecated.
visible
True when predicate can be called without raising a predicate existence error. This means
that the predicate is (1) defined, (2) can be inherited from one of the default modules (see
default module/2) or (3) can be autoloaded. The behaviour is logically consistent
iff the property visible is provided explicitly. If the property is left unbound, only
defined predicates are enumerated.
volatile
If true, the clauses are not saved into a saved state by qsave program/[1,2]. This
property is set using volatile/1.
?- use_module(library(lists)).
...
?- nth_clause(append(_,_,_), 2, Ref), clause(Head, Body, Ref).
Ref = <clause>(0x994290),
Head = lists:append([_G23|_G24], _G21, [_G23|_G27]),
Body = append(_G24, _G21, _G27).
file(FileName)
Unify FileName with the name of the file from which the clause is loaded. Fails if the
clause was not created by loading a file (e.g., clauses added using assertz/1). See
also source.
line count(LineNumber)
Unify LineNumber with the line number of the clause. Fails if the clause is not associated
to a file.
size(SizeInBytes)
True when SizeInBytes is the size that the clause uses in memory in bytes. The size
required by a predicate also includes the predicate data record, a linked list of clauses,
clause selection instructions and optionally one or more clause indexes.
source(FileName)
Unify FileName with the name of the source file that created the clause. This is the same
as the file property, unless the file is loaded from a file that is textually included into
source using include/1. In this scenario, file is the included file, while the source
property refers to the main file.
fact
True if the clause has no body.
erased
True if the clause has been erased, but not yet reclaimed because it is referenced.
predicate(PredicateIndicator)
PredicateIndicator denotes the predicate to which this clause belongs. This is needed to
obtain information on erased clauses because the usual way to obtain this information
using clause/3 fails for erased clauses.
module(Module)
Module is the context module used to execute the body of the clause. For normal clauses,
this is the same as the module in which the predicate is defined. However, if a clause
is compiled with a module qualified head, the clause belongs to the predicate with the
qualified head, while the body is executed in the context of the module in which the
clause was defined.
Compatibility Note that the ISO standard only defines the user * streams. The current streams
can be accessed using current input/1 and current output/1. For example, an ISO com-
patible implementation of write/1 is
alias(Atom)
Gives the stream a name. Below is an example. Be careful with this option as stream
names are global. See also set stream/2.
45
New code should use the alias(Alias) option for compatibility with the ISO standard.
...,
read(input, Term),
...
bom(Bool)
Check for a BOM (Byte Order Marker) or write one. If omitted, the default is true
for mode read and false for mode write. See also stream property/2 and
especially section 2.18.1 for a discussion of this feature.
buffer(Buffering)
Defines output buffering. The atom full (default) defines full buffering, line buffering
by line, and false implies the stream is fully unbuffered. Smaller buffering is useful
if another process or the user is waiting for the output as it is being produced. See also
flush output/[0,1]. This option is not an ISO option.
close on abort(Bool)
If true (default), the stream is closed on an abort (see abort/0). If false, the stream
is not closed. If it is an output stream, however, it will be flushed. Useful for logfiles and
if the stream is associated to a process (using the pipe/1 construct).
create(+List)
Specifies how a new file is created when opening in write, append or update mode.
Currently, List is a list of atoms that describe the permissions of the created file.46 Defined
values are below. Not recognised values are silently ignored, allowing for adding platform
specific extensions to this set.
read
Allow read access to the file.
write
Allow write access to the file.
execute
Allow execution access to the file.
default
Allow read and write access to the file.
all
Allow any access provided by the OS.
Note that if List is empty, the created file has no associated access permissions. The create
options map to the POSIX mode option of open(), where read map to 0444, write to
0222 and execute to 0111. On POSIX systems, the final permission is defined as (mode
& umask).
encoding(Encoding)
Define the encoding used for reading and writing text to this stream. The default encoding
for type text is derived from the Prolog flag encoding. For binary streams the
default encoding is octet. For details on encoding issues, see section 2.18.1.
46
Added after feedback from Joachim Shimpf and Per Mildner.
eof action(Action)
Defines what happens if the end of the input stream is reached. Action eof code makes
get0/1 and friends return -1, and read/1 and friends return the atom end of file.
Repetitive reading keeps yielding the same result. Action error is like eof code, but
repetitive reading will raise an error. With action reset, Prolog will examine the file
again and return more data if the file has grown.
locale(+Locale)
Set the locale that is used by notably format/2 for output on this stream. See sec-
tion 4.23.
lock(LockingMode)
Try to obtain a lock on the open file. Default is none, which does not lock the file. The
value read or shared means other processes may read the file, but not write it. The
value write or exclusive means no other process may read or write the file.
Locks are acquired through the POSIX function fcntl() using the command F SETLKW,
which makes a blocked call wait for the lock to be released. Please note that fcntl() locks
are advisory and therefore only other applications using the same advisory locks honour
your lock. As there are many issues around locking in Unix, especially related to NFS
(network file system), please study the fcntl() manual page before trusting your locks!
The lock option is a SWI-Prolog extension.
type(Type)
Using type text (default), Prolog will write a text file in an operating system compatible
way. Using type binary the bytes will be read or written without any translation. See
also the option encoding.
wait(Bool)
This option can be combined with the lock option. If false (default true), the open
call returns immediately with an exception if the file is locked. The exception has the
format permission error(lock, source sink, SrcDest).
The option reposition is not supported in SWI-Prolog. All streams connected to a file may
be repositioned.
write_length(Term, Len) :-
open_null_stream(Out),
write(Out, Term),
character_count(Out, Len0),
close(Out),
Len = Len0.
close(+Stream) [ISO]
Close the specified stream. If Stream is not open, an existence error is raised. See
stream pair/3 for the implications of closing a stream pair.
If the closed stream is the current input, output or error stream, the stream alias is bound to the
initial standard I/O streams of the process. Calling close/1 on the initial standard I/O streams
of the process is a no-op for an input stream and flushes an output stream without closing it.47
close(+Stream, +Options) [ISO]
Provides close(Stream, [force(true)]) as the only option. Called this way, any resource errors
(such as write errors while flushing the output buffer) are ignored.
stream property(?Stream, ?StreamProperty) [ISO]
True when StreamProperty is a property of Stream. If enumeration of streams or properties
is demanded because either Stream or StreamProperty are unbound, the implementation
enumerates all candidate streams and properties while locking the stream database. Properties
are fetched without locking the stream and may be outdated before this predicate returns due to
asynchronous activity.
alias(Atom)
If Atom is bound, test if the stream has the specified alias. Otherwise unify Atom with the
first alias of the stream.48
buffer(Buffering)
SWI-Prolog extension to query the buffering mode of this stream. Buffering is one of
full, line or false. See also open/4.
buffer size(Integer)
SWI-Prolog extension to query the size of the I/O buffer associated to a stream in bytes.
Fails if the stream is not buffered.
bom(Bool)
If present and true, a BOM (Byte Order Mark) was detected while opening the file for
reading, or a BOM was written while opening the stream. See section 2.18.1 for details.
close on abort(Bool)
Determine whether or not abort/0 closes the stream. By default streams are closed.
close on exec(Bool)
Determine whether or not the stream is closed when executing a new process (exec() in
Unix, CreateProcess() in Windows). Default is to close streams. This maps to fcntl()
F SETFD using the flag FD CLOEXEC on Unix and (negated) HANDLE FLAG INHERIT
on Windows.
encoding(Encoding)
Query the encoding used for text. See section 2.18.1 for an overview of wide character
and encoding issues in SWI-Prolog.
47
This behaviour was defined with purely interactive usage of Prolog in mind. Applications should not count on this
behaviour. Future versions may allow for closing the initial standard I/O streams.
48
BUG: Backtracking does not give other aliases.
end of stream(E)
If Stream is an input stream, unify E with one of the atoms not, at or past. See also
at end of stream/[0,1].
eof action(A)
Unify A with one of eof code, reset or error. See open/4 for details.
file name(Atom)
If Stream is associated to a file, unify Atom to the name of this file.
file no(Integer)
If the stream is associated with a POSIX file descriptor, unify Integer with the descriptor
number. SWI-Prolog extension used primarily for integration with foreign code. See also
Sfileno() from SWI-Stream.h.
input
True if Stream has mode read.
locale(Locale)
True when Locale is the current locale associated with the stream. See section 4.23.
mode(IOMode)
Unify IOMode to the mode given to open/4 for opening the stream. Values are: read,
write, append and the SWI-Prolog extension update.
newline(NewlineMode)
One of posix or dos. If dos, text streams will emit \r\n for \n and discard \r from
input streams. Default depends on the operating system.
nlink(-Count)
Number of hard links to the file. This expresses the number of names the file has. Not
supported on all operating systems and the value might be bogus. See the documentation
of fstat() for your OS and the value st nlink.
output
True if Stream has mode write, append or update.
position(Pos)
Unify Pos with the current stream position. A stream position is an opaque
term whose fields can be extracted using stream position data/3. See also
set stream position/2.
reposition(Bool)
Unify Bool with true if the position of the stream can be set (see seek/4). It is assumed
the position can be set if the stream has a seek-function and is not based on a POSIX file
descriptor that is not associated to a regular file.
representation errors(Mode)
Determines behaviour of character output if the stream cannot represent a character. For
example, an ISO Latin-1 stream cannot represent Cyrillic characters. The behaviour is
one of error (throw an I/O error exception), prolog (write \...\ escape code) or
xml (write &#...; XML character entity). The initial mode is prolog for the user
streams and error for all other streams. See also section 2.18.1 and set stream/2.
timeout(-Time)
Time is the timeout currently associated with the stream. See set stream/2 with the
same option. If no timeout is specified, Time is unified to the atom infinite.
type(Type)
Unify Type with text or binary.
tty(Bool)
This property is reported with Bool equal to true if the stream is associated with a
terminal. See also set stream/2.
is stream(+Term)
True if Term is a stream name or valid stream handle. This predicate realises a safe test for the
existence of a stream alias or handle.
non-binary files (see open/4) is of limited use, especially when using multi-byte text
encodings (e.g. UTF-8) or multi-byte newline files (e.g. DOS/Windows). On text files,
SWI-Prolog offers reliable backup to an old position using stream property/2 and
set stream position/2. Skipping N character codes is achieved calling get code/2
N times or using copy stream data/3, directing the output to a null stream (see
open null stream/1). If the seek modifies the current location, the line number and char-
acter position in the line are set to 0.
If the stream cannot be repositioned, a permission error is raised. If applying the offset
would result in a file position less than zero, a domain error is raised. Behaviour when
seeking to positions beyond the size of the underlying object depend on the object and possi-
bly the operating system. The predicate seek/4 is compatible with Quintus Prolog, though
the error conditions and signalling is ISO compliant. See also stream property/2 and
set stream position/2.
alias(AliasName)
Set the alias of an already created stream. If AliasName is the name of one of the standard
streams, this stream is rebound. Thus, set stream(S, current input) is the
same as set input/1, and by setting the alias of a stream to user input, etc., all
user terminal input is read from this stream. See also interactor/0.
buffer(Buffering)
Set the buffering mode of an already created stream. Buffering is one of full, line or
false.
buffer size(+Size)
Set the size of the I/O buffer of the underlying stream to Size bytes.
close on abort(Bool)
Determine whether or not the stream is closed by abort/0. By default, streams are
closed.
close on exec(Bool)
Set the close on exec property. See stream property/2.
encoding(Atom)
Defines the mapping between bytes and character codes used for the stream. See sec-
tion 2.18.1 for supported encodings. The value bom causes the stream to check whether
the current character is a Unicode BOM marker. If a BOM marker is found, the encoding
is set accordingly and the call succeeds. Otherwise the call fails.
eof action(Action)
Set end-of-file handling to one of eof code, reset or error.
file name(FileName)
Set the filename associated to this stream. This call can be used to set the file for error
locations if Stream corresponds to FileName and is not obtained by opening the file
directly but, for example, through a network service.
line position(LinePos)
Set the line position attribute of the stream. This feature is intended to correct position
management of the stream after sending a terminal escape sequence (e.g., setting ANSI
character attributes). Setting this attribute raises a permission error if the stream does
not record positions. See line position/2 and stream property/2 (property
position).
locale(+Locale)
Change the locale of the stream. See section 4.23.
newline(NewlineMode)
Set input or output translation for newlines. See corresponding stream property/2
for details. In addition to the detected modes, an input stream can be set in mode
detect. It will be set to dos if a \r character was removed.
timeout(Seconds)
This option can be used to make streams generate an exception if it takes longer than
Seconds before any new data arrives at the stream. The value infinite (default) makes the
stream block indefinitely. Like wait for input/3, this call only applies to streams
that support the select() system call. For further information about timeout handling, see
wait for input/3. The exception is of the form
error(timeout error(read, Stream), )
type(Type)
Set the type of the stream to one of text or binary. See also open/4 and the
encoding property of streams. Switching to binary sets the encoding to octet.
Switching to text sets the encoding to the default text encoding.
record position(Bool)
Do/do not record the line count and line position (see line count/2 and
line position/2).
representation errors(Mode)
Change the behaviour when writing characters to the stream that cannot be represented
by the encoding. See also stream property/2 and section 2.18.1.
tty(Bool)
Modify whether Prolog thinks there is a terminal (i.e. human interaction) connected
to this stream. On Unix systems the initial value comes from isatty(). On Win-
dows, the initial user streams are supposed to be associated to a terminal. See also
stream property/2.
for user error. Output buffering for Out is set to line and buffering on Error is
disabled. See also prolog/0 and set stream/2. The clib package provides the library
prolog server, creating a TCP/IP server for creating an interactive session to Prolog.
Another example of using the pipe/1 construct is shown below.52 Note that the pipe/1 con-
struct is not part of Prologs standard I/O repertoire.
getwd(Wd) :-
seeing(Old), see(pipe(pwd)),
collect_wd(String),
seen, see(Old),
atom_codes(Wd, String).
collect_wd([C|R]) :-
get0(C), C \== -1, !,
collect_wd(R).
collect_wd([]).
The effect of tell/1 is not undone on backtracking, and since the stream handle is not specified
explicitly in further I/O operations when using Edinburgh-style I/O, you may write to unintended
streams more easily than when using ISO compliant I/O. For example, the following query writes
both a and b into the file out :
51
The ISO I/O layer uses user input, user output and user error.
52
As of version 5.3.15, the pipe construct is supported in the MS-Windows version, both for swipl.exe and
swipl-win.exe. The implementation uses code from the LUA programming language (http://www.lua.org).
Compatibility notes
Unlike Edinburgh Prolog systems, telling/1 and seeing/1 do not return the filename of the
current input/output but rather the stream identifier, to ensure the design pattern below works under
all circumstances:53
...,
telling(Old), tell(x),
...,
told, tell(Old),
...,
The predicates tell/1 and see/1 first check for user, the pipe(command) and a stream handle.
Otherwise, if the argument is an atom it is first compared to open streams associated to a file with
exactly the same name. If such a stream exists, created using tell/1 or see/1, output (input) is
switched to the open stream. Otherwise a file with the specified name is opened.
The behaviour is compatible with Edinburgh Prolog. This is not without problems. Changing
directory, non-file streams, and multiple names referring to the same file easily lead to unexpected
behaviour. New code, especially when managing multiple I/O channels, should consider using the
ISO I/O predicates defined in section 4.17.2.
see(+SrcDest)
Open SrcDest for reading and make it the current input (see set input/1). If SrcDest is a
stream handle, just make this stream the current input. See the introduction of section 4.17.3
for details.
tell(+SrcDest)
Open SrcDest for writing and make it the current output (see set output/1). If SrcDest is a
stream handle, just make this stream the current output. See the introduction of section 4.17.3
for details.
append(+File)
Similar to tell/1, but positions the file pointer at the end of File rather than truncating an
existing file. The pipe construct is not accepted by this predicate.
seeing(?SrcDest)
Same as current input/1, except that user is returned if the current input is the stream
user input to improve compatibility with traditional Edinburgh I/O. See the introduction of
section 4.17.3 for details.
telling(?SrcDest)
Same as current output/1, except that user is returned if the current output is the stream
user output to improve compatibility with traditional Edinburgh I/O. See the introduction
of section 4.17.3 for details.
seen
Close the current input stream. The new input stream becomes user input.
told
Close the current output stream. The new output stream becomes user output.
53
Filenames can be ambiguous and SWI-Prolog streams can refer to much more than just files.
?- phrase(term(hello), X).
codes(-Codes)
Create a list of character codes from the emitted characters, similar to atom codes/2.
codes(-Codes, -Tail)
Create a list of character codes as a difference list.
chars(-Chars)
Create a list of one-character atoms from the emitted characters, similar to
atom chars/2.
chars(-Chars, -Tail)
Create a list of one-character atoms as a difference list.
Using write canonical/2 allows or exchange of terms with other Prolog systems. The
format is stable and, as it is text based, it can be inspected and corrected.
The binary format can deal with cycles, sharing and attributes. Special precautions are
needed to transfer such terms using write canonical/2. See term factorized/3
and copy term/3.
In the current version, reading the binary format has only incomplete consistency checks. This
implies a user must be able to trust the source as crafted messages may compromise the reading
Prolog system.
When available, the implementation is based on the poll() system call. The poll() puts no ad-
ditional restriction on the number of open files the process may have. It does limit the time
to 231 1 milliseconds (a bit less than 25 days). Specifying a too large timeout raises a
representation error(timeout) exception. If poll() is not supported by the OS, select()
is used. The select() call can only handle file descriptors up to FD SETSIZE. If the set contains
a descriptor that exceeds this limit a representation error(FD SETSIZE) is raised.
Note that wait for input/3 returns streams that have data waiting. This does not mean
you can, for example, call read/2 on the stream without blocking as the stream might hold an
incomplete term. The predicate set stream/2 using the option timeout(Seconds) can be
used to make the stream generate an exception if no new data arrives within the timeout period.
Suppose two processes communicate by exchanging Prolog terms. The following code makes
the server immune for clients that write an incomplete term:
...,
tcp_accept(Server, Socket, _Peer),
tcp_open(Socket, In, Out),
set_stream(In, timeout(10)),
catch(read(In, Term), _, (close(Out), close(In), fail)),
...,
nl [ISO]
Write a newline character to the current output stream. On Unix systems nl/0 is equivalent to
put(10).
nl(+Stream) [ISO]
Write a newline to Stream.
put(+Char)
Write Char to the current output stream. Char is either an integer expression evaluating to a
character code or an atom of one character. Deprecated. New code should use put char/1
or put code/1.
put(+Stream, +Char)
Write Char to Stream. See put/1 for details.
tab(+Amount)
Write Amount spaces on the current output stream. Amount should be an expression that evalu-
ates to a positive integer (see section 4.27).
tab(+Stream, +Amount)
Write Amount spaces to Stream.
ttyflush
Flush pending output on stream user. See also flush output/[0,1].
get0(-Char) [deprecated]
Edinburgh version of the ISO get code/1 predicate. Note that Edinburgh Prolog didnt
support wide characters and therefore technically speaking get0/1 should have been mapped
to get byte/1. The intention of get0/1, however, is to read character codes.
get(-Char) [deprecated]
Read the current input stream and unify the next non-blank character with Char. Char is
unified with -1 on end of file. The predicate get/1 operates on character codes. See also
get0/1.
skip(+Code)
Read the input until Code or the end of the file is encountered. A subsequent call to
get code/1 will read the first character after Code.
skip(+Stream, +Code)
Skip input (as skip/1) on Stream.
copy(In, Out) :-
repeat,
fill_buffer(In),
read_pending_codes(In, Chars, Tail),
\+ \+ ( Tail = [],
format(Out, s, [Chars]),
flush_output(Out)
),
( Tail == []
-> !
; fail
).
attributes(Atom)
Define how attributed variables (see section 7.1) are written. The default is determined by
the Prolog flag write attributes. Defined values are ignore (ignore the attribute),
dots (write the attributes as {...}), write (simply hand the attributes recursively to
write term/2) and portray (hand the attributes to attr portray hook/2).
back quotes(Atom)
Fulfills the same role as the back quotes prolog flag. Notably, the value string
causes string objects to be printed between back quotes and symbol char causes the
backquote to be printed unquoted. In all other cases the backquote is printed as a quoted
atom.
brace terms(Bool)
If true (default), write {}(X) as {X}. See also dotlists and ignore ops.
blobs(Atom)
Define how non-text blobs are handled. By default, this is left to the write handler spec-
ified with the blob type. Using portray, portray/1 is called for each blob
encountered. See section 11.4.7.
character escapes(Bool)
If true and quoted(true) is active, special characters in quoted atoms and strings are
emitted as ISO escape sequences. Default is taken from the reference module (see below).
cycles(Bool)
If true (default), cyclic terms are written as @(Template, Substitutions), where Substi-
tutions is a list Var = Value. If cycles is false, max depth is not given, and Term
is cyclic, write term/2 raises a domain error.56 See also the cycles option in
read term/2.
dotlists(Bool)
If true (default false), write lists using the dotted term notation rather than the list no-
tation.57 Note that as of version 7, the list constructor is [|]. Using dotlists(true),
write term/2 writes a list using . as constructor. This is intended for communication
with programs such as other Prolog systems, that rely on this notation.
56
The cycles option and the cyclic term representation using the @-term are copied from SICStus Prolog. However, the
default in SICStus is set to false and SICStus writes an infinite term if not protected by, e.g., the depth limit option.
57
Copied from ECLiPSe.
fullstop(Bool)
If true (default false), add a fullstop token to the output. The dot is preceeded by a
space if needed and followed by a space (default) or newline if the nl(true) option is also
given.58
ignore ops(Bool)
If true, the generic term representation (hfunctori(hargsi . . . )) will be used for all terms.
Otherwise (default), operators will be used where appropriate.59 .
max depth(Integer)
If the term is nested deeper than Integer, print the remainder as ellipses (. . . ). A 0 (zero)
value (default) imposes no depth limit. This option also delimits the number of printed
items in a list. Example:
?- write_term(a(s(s(s(s(0)))), [a,b,c,d,e,f]),
[max_depth(3)]).
a(s(s(...)), [a, b|...])
true.
Used by the top level and debugger to limit screen output. See also the Prolog flags
answer write options and debugger write options.
module(Module)
Define the reference module (default user). This defines the default value for the
character escapes option as well as the operator definitions to use. See also op/3.
nl(Bool)
Add a newline to the output. See also the fullstop option.
numbervars(Bool)
If true, terms of the format $VAR(N), where N is a non-negative integer, will be written
as a variable name. If N is an atom it is written without quotes. This extension allows
for writing variables with user-provided names. The default is false. See also
numbervars/3 and the option variable names.
partial(Bool)
If true (default false), do not reset the logic that inserts extra spaces that separate
tokens where needed. This is intended to solve the problems with the code below. Calling
write value(.) writes .., which cannot be read. By adding partial(true) to the
option list, it correctly emits . .. Similar problems appear when emitting operators
using multiple calls to write term/3.
write_value(Value) :-
write_term(Value, [partial(true)]),
write(.), nl.
portray(Bool)
Same as portrayed(Bool). Deprecated.
58
Compatible with ECLiPSe
59
In traditional systems this flag also stops the syntactic sugar notation for lists and brace terms. In SWI-Prolog, these
are controlled by the separate options dotlists and brace terms
portray goal(:Goal)
Implies portray(true), but calls Goal rather than the predefined hook portray/1.
Goal is called through call/3, where the first argument is Goal, the second is the term
to be printed and the 3rd argument is the current write option list. The write option list is
copied from the write term call, but the list is guaranteed to hold an option priority
that reflects the current priority.
portrayed(Bool)
If true, the hook portray/1 is called before printing a term that is not a variable. If
portray/1 succeeds, the term is considered printed. See also print/1. The default
is false. This option is an extension to the ISO write term options.
priority(Integer)
An integer between 0 and 1200 representing the context priority. Default is 1200. Can
be used to write partial terms appearing as the argument to an operator. For example:
format(w = , [VarName]),
write_term(Value, [quoted(true), priority(699)])
quoted(Bool)
If true, atoms and functors that need quotes will be quoted. The default is false.
spacing(+Spacing)
Determines whether and where extra white space is added to enhance readability. The
default is standard, adding only space where needed for proper tokenization by
read term/3. Currently, the only other value is next argument, adding a space
after a comma used to separate arguments in a term or list.
variable names(+List)
Assign names to variables in Term. List is a list of terms Name = Var, where Name is
an atom that represents a valid Prolog variable name. Terms where Var is bound or is
a variable that does not appear in Term are ignored. Raises an error if List is not a list,
one of the members is not a term Name = Var, Name is not an atom or Name does not
represent a valid Prolog variable name.
The implementation binds the variables from List to a term $VAR(Name). Like
write canonical/1, terms that where already bound to $VAR(X) before
write term/2 are printed normally, unless the option numbervars(true) is also pro-
vided. If the option numbervars(true) is used, the user is responsible for avoiding col-
lisions between assigned names and numbered names. See also the variable names
option of read term/2.
Possible variable attributes (see section 7.1) are ignored. In most cases one should use
copy term/3 to obtain a copy that is free of attributed variables and handle the associ-
ated constraints as appropriate for the use-case.
max length(+MaxLength)
If provided, fail if Length would be larger than MaxLength. The implementation ensures
that the runtime is limited when computing the length of a huge term with a bounded
maximum.
write(+Term) [ISO]
Write Term to the current output, using brackets and operators where appropriate.
writeq(+Term) [ISO]
Write Term to the current output, using brackets and operators where appropriate. Atoms that
need quotes are quoted. Terms written with this predicate can be read back with read/1
provided the currently active operator declarations are identical.
writeln(+Term)
Equivalent to write(Term), nl.. The output stream is locked, which implies no output
from other threads can appear between the term and newline.
writeln(+Stream, +Term)
Equivalent to write(Stream, Term), nl(Stream).. The output stream is locked,
which implies no output from other threads can appear between the term and newline.
print(+Term)
Print a term for debugging purposes. The predicate print/1 acts as if defined as below.
print(Term) :-
current_prolog_flag(print_write_options, Options), !,
write_term(Term, Options).
print(Term) :-
write_term(Term, [ portray(true),
numbervars(true),
quoted(true)
]).
The print/1 predicate is used primarily through the p escape sequence of format/2,
which is commonly used in the recipies used by print message/2 to emit messages.
The classical definition of this predicate is equivalent to the ISO predicate write term/2
using the options portray(true) and numbervars(true). The portray(true) option al-
lows the user to implement application-specific printing of terms printed during debugging to
facilitate easy understanding of the output. See also portray/1 and portray text. SWI-
Prolog adds quoted(true) to (1) facilitate the copying/pasting of terms that are not affected by
portray/1 and to (2) allow numbers, atoms and strings to be more easily distinguished, e.g.,
42, 42 and "42".
print(+Stream, +Term)
Print Term to Stream.
portray(+Term)
A dynamic predicate, which can be defined by the user to change the behaviour of print/1
on (sub)terms. For each subterm encountered that is not a variable print/1 first calls
portray/1 using the term as argument. For lists, only the list as a whole is given to
portray/1. If portray/1 succeeds print/1 assumes the term has been written.
read(-Term) [ISO]
Read the next Prolog term from the current input stream and unify it with Term. On a syntax
error read/1 displays an error message, attempts to skip the erroneous term and fails. On
reaching end-of-file Term is unified with the atom end of file.
syntax errors(+Atom)
See read term/3, but the default is dec10 (report and restart).
term position(-TermPos)
Same as for read term/3.
subterm positions(-TermPos)
Same as for read term/3.
variable names(-Bindings)
Same as for read term/3.
process comment(+Boolean)
If true (default), call prolog:comment hook(Comments, TermPos, Term) if this
multifile hook is defined (see prolog:comment hook/3). This is used to drive PlDoc.
comments(-Comments)
If provided, unify Comments with the comments encountered while reading Term. This
option implies process comment(false).
The singletons option of read term/3 is initialised from the active style-checking
mode. The module option is initialised to the current compilation module (see
prolog load context/2).
backquoted string(Bool)
If true, read . . . to a string object (see section 5.2). The default depends on the
Prolog flag back quotes.
character escapes(Bool)
Defines how to read \ escape sequences in quoted atoms. See the Prolog flag
character escapes in current prolog flag/2. (SWI-Prolog).
comments(-Comments)
Unify Comments with a list of Position-Comment, where Position is a stream position
object (see stream position data/3) indicating the start of a comment and
Comment is a string object containing the text including delimiters of a comment. It
returns all comments from where the read term/2 call started up to the end of the
term read.
cycles(Bool)
If true (default false), re-instantiate templates as produced by the corresponding
write term/2 option. Note that the default is false to avoid misinterpretation
of @(Template, Substutions), while the default of write term/2 is true because
emitting cyclic terms without using the template construct produces an infinitely large
term (read: it will generate an error after producing a huge amount of output).
dotlists(Bool)
If true (default false), read .(a,[]) as a list, even if lists are internally nor con-
structed using the dot as functor. This is primarily intended to read the output from
write canonical/1 from other Prolog systems. See section 5.1.
double quotes(Atom)
Defines how to read . . . strings. See the Prolog flag double quotes. (SWI-Prolog).
module(Module)
Specify Module for operators, character escapes flag and double quotes flag.
The value of the latter two is overruled if the corresponding read term/3 option is
provided. If no module is specified, the current source module is used. (SWI-Prolog).
quasi quotations(-List)
If present, unify List with the quasi quotations (see section A.27) instead of evaluating
prompt(-Old, +New)
Set prompt associated with read/1 and its derivatives. Old is first unified with the current
prompt. On success the prompt will be set to New if this is an atom. Otherwise an error
message is displayed. A prompt is printed if one of the read predicates is called and the cursor
is at the left margin. It is also printed whenever a newline is given and the term has not been
terminated. Prompts are only printed when the current input stream is user.
prompt1(+Prompt)
Sets the prompt for the next line to be read. Continuation lines will be read using the prompt
defined by prompt/2.
?- functor(a(), N, A).
N = a, A = 0.
?- functor(T, a, 0).
T = a.
SWI-Prolog also supports terms with arity 0, as in a() (see section 5. Such terms must be
processed using compound name arguments/3. This predicate raises a domain error as
shown below. See also functor/3.
60
Raising a domain error was suggested by Jeff Schultz.
61
The instantiation pattern (-, +, ?) is an extension to standard Prolog. Some systems provide genarg/3 that covers
this pattern.
?- a() =.. L.
ERROR: Domain error: compound_non_zero_arity expected, found a()
?- Term = f(X,Y,X),
numbervars(Term, 0, End),
write_canonical(Term), nl.
f($VAR(0),$VAR(1),$VAR(0))
Term = f(A, B, A),
X = A,
Y = B,
End = 2.
functor name(+Atom)
Name of the functor to use instead of $VAR.
attvar(+Action)
What to do if an attributed variable is encountered. Options are skip, which causes
numbervars/3 to ignore the attributed variable, bind which causes it to thread it as
a normal variable and assign the next $VAR(N) term to it, or (default) error which
raises a type error exception.63
62
BUG: Only tagged integers are supported (see the Prolog flag max tagged integer). This suffices to count all
variables that can appear in the largest term that can be represented, but does not support arbitrary large integer values for
Start. On overflow, a representation error(tagged integer) exception is raised.
63
This behaviour was decided after a long discussion between David Reitter, Richard OKeefe, Bart Demoen and Tom
Schrijvers.
singletons(+Bool)
If true (default false), numbervars/4 does singleton detection. Singleton variables
are unified with $VAR(_), causing them to be printed as _ by write term/2
using the numbervars option. This option is exploited by portray clause/2 and
write canonical/2.64
Prolog systems and one has to be very careful about unexpected copying as well as unexpected
noncopying of terms. A good practice to improve somewhat on this situation is to make sure that
terms whose arguments are subject to setarg/3 have one unused and unshared variable in
addition to the used arguments. This variable avoids unwanted sharing in, e.g., copy term/2,
and causes the term to be considered as non-ground. An alternative is to use put attr/3 to
attach information to attributed variables (see section 7.1).
:- meta_predicate
succeeds_n_times(0, -).
succeeds_n_times(Goal, Times) :-
Counter = counter(0),
( Goal,
arg(1, Counter, N0),
N is N0 + 1,
nb_setarg(1, Counter, N),
fail
; arg(1, Counter, Times)
).
?- atom_chars(hello, X).
X = [h, e, l, l, o]
name(?Atomic, ?CodeList)
CodeList is a list of character codes representing the same text as Atomic. Each of the argu-
ments may be a variable, but not both. When CodeList describes an integer or floating point
number and Atomic is a variable, Atomic will be unified with the numeric value described by
CodeList (e.g., name(N, "300"), 400 is N + 100 succeeds). If CodeList is not a
representation of a number, Atomic will be unified with the atom with the name given by the
character code list. When Atomic is an atom or number, the unquoted print representation of it
as a character code list will be unified with CodeList.
Note that it is not possible to produce the atom 300 using name/2, and that
name(300, CodeList), name(300, CodeList) succeeds. For these reasons,
new code should consider using the ISO predicates atom codes/2 or number codes/2.70
See also atom number/2.
A = gnu, gnat
The SWI-Prolog version of this predicate can also be used to split atoms by instantiating Sepa-
rator and Atom as shown below. We kept this functionality to simplify porting old SWI-Prolog
code where this predicate was called concat atom/3. When used in mode (-,+,+), Separator
must be a non-empty atom. See also split string/4.
?- atomic_list_concat(L, -, gnu-gnat).
L = [gnu, gnat]
?- sub_atom(abc, 1, 1, A, S).
A = 1, S = b
The implementation minimises non-determinism and creation of atoms. This is a flexible pred-
icate that can do search, prefix- and suffix-matching, etc.
The predicates char type/2 and code type/2 query character classes depending on the
locale.
The predicates collation key/2 and locale sort/2 can be used for locale dependent
sorting of atoms.
The predicate format time/3 can be used to format time and date representations, where
some of the specifiers are locale dependent.
A locale is a (optionally named) read-only object that provides information to locale specific
functions.72 The system creates a default locale object named default from the system locale. This
locale is used as the initial locale for the three standard streams as well as the main thread. Locale
sensitive output predicates such as format/3 get their locale from the stream to which they deliver
their output. New streams get their locale from the thread that created the stream. Threads get their
locale from the thread that created them.
alias(+Atom)
Give the locale a name.
decimal point(+Atom)
Specify the decimal point to use.
thousands sep(+Atom)
Specify the string that delimits digit groups. Only effective is grouping is also specified.
71
This predicate replaces $apropos match/2, used by the help system, while extending it with locating the (first) match
and performing case insensitive prefix matching. We are still not happy with the name and interface.
72
The locale interface described in this section and its effect on format/2 and reading integers from digit groups was
discussed on the SWI-Prolog mailinglist. Most input in this discussion is from Ulrich Neumerkel and Richard OKeefe.
The predicates in this section were designed by Jan Wielemaker.
grouping(+List)
Specify the grouping of digits. Groups are created from the right (least significant) digits,
left of the decimal point. List is a list of integers, specifying the number of digits in each
group, counting from the right. If the last element is repeat(Count), the remaining
digits are grouped in groups of size Count. If the last element is a normal integer, digits
further to the left are not grouped.
Named locales exists until they are destroyed using locale destroy/1 and they are no
longer referenced. Unnamed locales are subject to (atom) garbage collection.
locale destroy(+Locale)
Destroy a locale. If the locale is named, this removes the name association from the locale,
after which the locale is left to be reclaimed by garbage collection.
set locale(+Locale)
Set the default locale for the current thread, as well as the locale for the standard streams
(user input, user output, user error, current output and current input.
This locale is used for new streams, unless overruled using the locale(Locale) option of
open/4 or set stream/2.
current locale(-Locale)
True when Locale is the locale of the calling thread.
alnum
Char is a letter (upper- or lowercase) or digit.
alpha
Char is a letter (upper- or lowercase).
csym
Char is a letter (upper- or lowercase), digit or the underscore (_). These are valid C and
Prolog symbol characters.
csymf
Char is a letter (upper- or lowercase) or the underscore (_). These are valid first characters
for C and Prolog symbols.
ascii
Char is a 7-bit ASCII character (0..127).
white
Char is a space or tab, i.e. white space inside a line.
cntrl
Char is an ASCII control character (0..31).
digit
Char is a digit.
digit(Weight)
Char is a digit with value Weight. I.e. char type(X, digit(6) yields X = 6.
Useful for parsing numbers.
xdigit(Weight)
Char is a hexadecimal digit with value Weight. I.e. char type(a, xdigit(X)
yields X = 10. Useful for parsing numbers.
graph
Char produces a visible mark on a page when printed. Note that the space is not included!
lower
Char is a lowercase letter.
lower(Upper)
Char is a lowercase version of Upper. Only true if Char is lowercase and Upper upper-
case.
to lower(Upper)
Char is a lowercase version of Upper. For non-letters, or letter without case, Char and
Lower are the same. See also upcase atom/2 and downcase atom/2.
upper
Char is an uppercase letter.
upper(Lower)
Char is an uppercase version of Lower. Only true if Char is uppercase and Lower lower-
case.
to upper(Lower)
Char is an uppercase version of Lower. For non-letters, or letter without case, Char and
Lower are the same. See also upcase atom/2 and downcase atom/2.
punct
Char is a punctuation character. This is a graph character that is not a letter or digit.
space
Char is some form of layout character (tab, vertical tab, newline, etc.).
end of file
Char is -1.
end of line
Char ends a line (ASCII: 10..13).
newline
Char is a newline character (10).
period
Char counts as the end of a sentence (.,!,?).
quote
Char is a quote character (", , ).
paren(Close)
Char is an open parenthesis and Close is the corresponding close parenthesis.
prolog var start
Char can start a Prolog variable name.
prolog atom start
Char can start a unquoted Prolog atom that is not a symbol.
prolog identifier continue
Char can continue a Prolog variable name or atom.
prolog prolog symbol
Char is a Prolog symbol character. Sequences of Prolog symbol characters glue together
to form an unquoted atom. Examples are =.., \=, etc.
4.25 Operators
Operators are defined to improve the readability of source code. For example, without operators, to
write 2*3+4*5 one would have to write +(*(2,3),*(4,5)). In Prolog, a number of operators
have been predefined. All operators, except for the comma (,) can be redefined by the user.
Some care has to be taken before defining new operators. Defining too many operators might
make your source natural looking, but at the same time make it hard to understand the limits of your
syntax. To ease the pain, as of SWI-Prolog 3.3.0, operators are local to the module in which they are
defined. Operators can be exported from modules using a term op(Precedence, Type, Name) in the
export list as specified by module/2. Many modern Prolog systems have module specific operators.
Unfortunately, there is no established interface for exporting and importing operators. SWI-Prologs
convention has been addopted by YAP.
The module table of the module user acts as default table for all modules and can be modified
explicitly from inside a module to achieve compatibility with other Prolog that do not have module-
local operators:
:- module(prove,
[ prove/1
]).
In SWI-Prolog, a quoted atom never acts as an operator. Note that the portable way to stop an atom
acting as an operator is to enclose it in parentheses like this: (myop). See also section 5.3.1.
In SWI-Prolog, operators are local to a module (see also section 6.8). Keeping operators in
modules and using controlled import/export of operators as described with the module/2 di-
rective keep the issues manageable. The module system provides the operators from table 4.2
and these operators cannot be modified. Files that are loaded from the SWI-Prolog directories
resolve operators and predicates from this system module rather than user, which makes the
semantics of the library and development system modules independent of operator changes to
the user module.
current op(?Precedence, ?Type, ?:Name) [ISO]
True if Name is currently defined as an operator of type Type with precedence Precedence. See
also op/3.
1200 xf x -->, :-
1200 fx :-, ?-
1150 fx dynamic, discontiguous, initialization,
meta predicate, module transparent, multifile,
public, thread local, thread initialization,
volatile
1100 xf y ;, |
1050 xf y ->, *->
1000 xf y ,
990 xf x :=
900 fy \+
700 xf x <, =, =.., =@=, \=@=, =:=, =<, ==, =\=, >, >=, @<, @=<, @>,
@>=, \=, \==, as, is, >:<, :<
600 xf y :
500 yf x +, -, /\, \/, xor
500 fx ?
400 yf x *, /, //, div, rdiv, <<, >>, mod, rem
200 xf x **
200 xf y
200 fy +, -, \
100 yf x .
1 fx $
4.27 Arithmetic
Arithmetic can be divided into some special purpose integer predicates and a series of general pred-
icates for integer, floating point and rational arithmetic as appropriate. The general arithmetic predi-
cates all handle expressions. An expression is either a simple number or a function. The arguments of
a function are expressions. The functions are described in section 4.27.2.
Note that this predicate is only available if SWI-Prolog is compiled with unbounded integer
support. This is the case for all packaged versions.
nth integer root and remainder(+N, +I, -Root, -Remainder)
True when RootN + Remainder = I. N and I must be integers.75 N must be one or more. If I
is negative and N is odd, Root and Remainder are negative, i.e., the following holds for I < 0:
73
We prefer infinite, but some other Prolog systems already use inf for infinity; we accept both for the time being.
74
The behaviour to deal with natural numbers only was defined by Richard OKeefe to support the common count-down-
to-zero in a natural way. Up to 5.1.8, succ/2 also accepted negative integers.
75
This predicate was suggested by Markus Triska. The final name and argument order is by Richard OKeefe. The
decision to include the remainder is by Jan Wielemaker. Including the remainder makes this predicate about twice as slow
if Root is not exact.
% I < 0,
% N mod 2 =\= 0,
nth_integer_root_and_remainder(
N, I, Root, Remainder),
IPos is -I,
nth_integer_root_and_remainder(
N, IPos, RootPos, RemainderPos),
Root =:= -RootPos,
Remainder =:= -RemainderPos.
Arithmetic types
integer
If SWI-Prolog is built using the GNU multiple precision arithmetic library (GMP), integer
arithmetic is unbounded, which means that the size of integers is limited by available memory
only. Without GMP, SWI-Prolog integers are 64-bits, regardless of the native integer size of
the platform. The type of integer support can be detected using the Prolog flags bounded,
min integer and max integer. As the use of GMP is default, most of the following
descriptions assume unbounded integer arithmetic.
Internally, SWI-Prolog has three integer representations. Small integers (defined by the Prolog
flag max tagged integer) are encoded directly. Larger integers are represented as 64-bit
values on the global stack. Integers that do not fit in 64 bits are represented as serialised GNU
MPZ structures on the global stack.
rational number
Rational numbers (Q) are quotients of two integers. Rational arithmetic is only provided if GMP
is used (see above). Rational numbers are currently not supported by a Prolog type. They are
represented by the compound term rdiv(N,M). Rational numbers that are returned from is/2
are canonical, which means M is positive and N and M have no common divisors. Rational
numbers are introduced in the computation using the rational/1, rationalize/1 or
the rdiv/2 (rational division) function. Using the same functor for rational division and for
representing rational numbers allows for passing rational numbers between computations as
well as for using format/3 for printing.
In the long term, it is likely that rational numbers will become atomic as well as a subtype of
number. User code that creates or inspects the rdiv(M,N) terms will not be portable to future
versions. Rationals are created using one of the functions mentioned above and inspected using
rational/3.
float
Floating point numbers are represented using the C type double. On most of todays platforms
these are 64-bit IEEE floating point numbers.
Arithmetic functions that require integer arguments accept, in addition to integers, rational num-
bers with (canonical) denominator 1. If the required argument is a float the argument is converted to
float. Note that conversion of integers to floating point numbers may raise an overflow exception. In
all other cases, arguments are converted to the same type using the order below.
integer rational number floating point number
Note that floats cannot represent all decimal numbers exactly. The function rational/1 creates
an exact equivalent of the float, while rationalize/1 creates a rational number that is within the
float rounding error from the original float. Please check the documentation of these functions for
details and examples.
Rational numbers can be printed as decimal numbers with arbitrary precision using the
format/3 floating point conversion:
?- A is 4 rdiv 3 + rational(1.5),
format(50fn, [A]).
2.83333333333333333333333333333333333333333333333333
A = 17 rdiv 6
Arithmetic Functions
Arithmetic functions are terms which are evaluated by the arithmetic predicates described in sec-
tion 4.27.2. There are four types of arguments to functions:
For systems using bounded integer arithmetic (default is unbounded, see section 4.27.2 for de-
tails), integer operations that would cause overflow automatically convert to floating point arithmetic.
SWI-Prolog provides many extensions to the set of floating point functions defined by the ISO
standard. The current policy is to provide such functions on as-needed basis if the function is widely
supported elsewhere and notably if it is part of the C99 mathematical library. In addition, we try to
maintain compatibility with YAP.
- +Expr [ISO]
Result = Expr
+ +Expr [ISO]
Result = Expr. Note that if + is followed by a number, the parser discards the +. I.e.
?- integer(+1) succeeds.
Q is div(X, Y),
M is mod(X, Y),
X =:= Y*Q+M.
abs(+Expr) [ISO]
Evaluate Expr and return the absolute value of it.
sign(+Expr) [ISO]
Evaluate to -1 if Expr < 0, 1 if Expr > 0 and 0 if Expr = 0. If Expr evaluates to a float, the
return value is a float (e.g., -1.0, 0.0 or 1.0). In particular, note that sign(-0.0) evaluates to 0.0.
See also copysign/2
76
Future versions might guarantee rounding towards zero.
.(+Int, [])
A list of one element evaluates to the element. This implies "a" evaluates to the character code
of the letter a (97) using the traditional mapping of double quoted string to a list of character
codes. Arithmetic evaluation also translates a string object (see section 5.2) of one character
length into the character code for that character. This implies that expression "a" also works
of the Prolog flag double quotes is set to string. The recommended way to specify the
character code of the letter a is 0a.
random(+IntExpr)
Evaluate to a random integer i for which 0 i < IntExpr. The system has two implemen-
tations. If it is compiled with support for unbounded arithmetic (default) it uses the GMP
library random functions. In this case, each thread keeps its own random state. The default
algorithm is the Mersenne Twister algorithm. The seed is set when the first random number in
a thread is generated. If available, it is set from /dev/random. Otherwise it is set from the
system clock. If unbounded arithmetic is not supported, random numbers are shared between
threads and the seed is initialised from the clock when SWI-Prolog was started. The predicate
set random/1 can be used to control the random number generator.
random float
Evaluate to a random float I for which 0.0 < i < 1.0. This function shares the random state with
random/1. All remarks with the function random/1 also apply for random float/0.
Note that both sides of the domain are open. This avoids evaluation errors on, e.g., log/1 or
//2 while no practical application can expect 0.0.77
round(+Expr) [ISO]
Evaluate Expr and round the result to the nearest integer. According to ISO, round/1 is
defined as floor(Expr+1/2), i.e., rounding down. This is an unconventional choice and
77
Richard OKeefe said: If you are generating IEEE doubles with the claimed uniformity, then 0 has a 1 in 253 =
1in9, 007, 199, 254, 740, 992 chance of turning up. No program that expects [0.0,1.0) is going to be surprised when 0.0
fails to turn up in a few millions of millions of trials, now is it? But a program that expects (0.0,1.0) could be devastated if
0.0 did turn up.
under which the relation round(Expr) == -round(-Expr) does not hold. SWI-Prolog
rounds outward, e.g., round(1.5) =:= 2 and round round(-1.5) =:= -2.
integer(+Expr)
Same as round/1 (backward compatibility).
float(+Expr) [ISO]
Translate the result to a floating point number. Normally, Prolog will use integers whenever
possible. When used around the 2nd argument of is/2, the result will be returned as a floating
point number. In other contexts, the operation has no effect.
rational(+Expr)
Convert the Expr to a rational number or integer. The function returns the input on integers
and rational numbers. For floating point numbers, the returned rational number exactly
represents the float. As floats cannot exactly represent all decimal numbers the results may be
surprising. In the examples below, doubles can represent 0.25 and the result is as expected, in
contrast to the result of rational(0.1). The function rationalize/1 remedies this. See
section 4.27.2 for more information on rational number support.
?- A is rational(0.25).
A is 1 rdiv 4
?- A is rational(0.1).
A = 3602879701896397 rdiv 36028797018963968
rationalize(+Expr)
Convert the Expr to a rational number or integer. The function is similar to rational/1,
but the result is only accurate within the rounding error of floating point numbers, generally
producing a much smaller denominator.78
?- A is rationalize(0.25).
A = 1 rdiv 4
?- A is rationalize(0.1).
A = 1 rdiv 10
truncate(+Expr) [ISO]
Truncate Expr to an integer. If Expr 0 this is the same as floor(Expr). For Expr < 0 this is
the same as ceil(Expr). That is, truncate/1 rounds towards zero.
floor(+Expr) [ISO]
Evaluate Expr and return the largest integer smaller or equal to the result of the evaluation.
ceiling(+Expr) [ISO]
Evaluate Expr and return the smallest integer larger or equal to the result of the evaluation.
ceil(+Expr)
Same as ceiling/1 (backward compatibility).
\ +IntExpr [ISO]
Bitwise negation. The returned value is the ones complement of IntExpr.
sqrt(+Expr) [ISO]
Result = Expr
sin(+Expr) [ISO]
Result = sin Expr. Expr is the angle in radians.
cos(+Expr) [ISO]
Result = cos Expr. Expr is the angle in radians.
tan(+Expr) [ISO]
Result = tan Expr. Expr is the angle in radians.
asin(+Expr) [ISO]
Result = arcsin Expr. Result is the angle in radians.
acos(+Expr) [ISO]
Result = arccos Expr. Result is the angle in radians.
atan(+Expr) [ISO]
Result = arctan Expr. Result is the angle in radians.
asinh(+Expr)
Result = arcsinh(Expr) (inverse hyperbolic sine).
acosh(+Expr)
Result = arccosh(Expr) (inverse hyperbolic cosine).
atanh(+Expr)
Result = arctanh(Expr). (inverse hyperbolic tangent).
log(+Expr) [ISO]
Natural logarithm. Result = ln Expr
log10(+Expr)
Base-10 logarithm. Result = lg Expr
exp(+Expr) [ISO]
Result = eExpr
+Expr1 ** +Expr2 [ISO]
Result = Expr1 Expr2 . The result is a float, unless SWI-Prolog is compiled with unbounded in-
teger support and the inputs are integers and produce an integer result. The integer expressions
0I , 1I and 1I are guaranteed to work for any integer I. Other integer base values generate a
resource error if the result does not fit in memory.
The ISO standard demands a float result for all inputs and introduces /2 for integer expo-
nentiation. The function float/1 can be used on one or both arguments to force a floating
point result. Note that casting the input result in a floating point computation, while casting the
output performs integer exponentiation followed by a conversion to float.
+Expr1 +Expr2 [ISO]
In SWI-Prolog, /2 is equivalent to **/2. The ISO version is similar, except that it produces
a evaluation error if both Expr1 and Expr2 are integers and the result is not an integer. The
table below illustrates the behaviour of the exponentiation functions in ISO and SWI.
lgamma(+Expr)
Return the natural logarithm of the absolute value of the Gamma function.80
erf(+Expr)
WikipediA: In mathematics, the error function (also called the Gauss error function) is a
special function (non-elementary) of sigmoid shape which occurs in probability, statistics and
partial differential equations.
erfc(+Expr)
WikipediA: The complementary error function.
pi [ISO]
Evaluate to the mathematical constant (3.14159. . . ).
e
Evaluate to the mathematical constant e (2.71828. . . ).
epsilon
Evaluate to the difference between the float 1.0 and the first larger floating point number.
inf
Evaluate to positive infinity. See section 2.15.1. This value can be negated using -/1.
nan
Evaluate to Not a Number. See section 2.15.1.
cputime
Evaluate to a floating point number expressing the CPU time (in seconds) used by Prolog up till
now. See also statistics/2 and time/1.
79
The underlying GMP mpz powm() function allows negative values under some conditions. As the conditions are
expensive to pre-compute, error handling from GMP is non-trivial and negative values are not needed for Diffie-Hellman
key-exchange we do not support these.
80
Some interfaces also provide the sign of the Gamma function. We canot do that in an arithmetic function. Future
versions may provide a predicate lgamma/3 that returns both the value and the sign.
eval(+Expr)
Evaluate Expr. Although ISO standard dictates that A=1+2, B is A works and unifies B to 3,
it is widely felt that source level variables in arithmetic expressions should have been limited
to numbers. In this view the eval function can be used to evaluate arbitrary expressions.81
Bitvector functions The functions below are not covered by the standard. The msb/1 function
also appears in hProlog and SICStus Prolog. The getbit/2 function also appears in ECLiPSe,
which also provides setbit(Vector,Index) and clrbit(Vector,Index). The others are SWI-Prolog
extensions that improve handling of unbounded integers as bit-vectors.
msb(+IntExpr)
Return the largest integer N such that (IntExpr >> N) /\ 1 =:= 1. This is the (zero-
origin) index of the most significant 1 bit in the value of IntExpr, which must evaluate to a
positive integer. Errors for 0, negative integers, and non-integers.
lsb(+IntExpr)
Return the smallest integer N such that (IntExpr >> N) /\ 1 =:= 1. This is the
(zero-origin) index of the least significant 1 bit in the value of IntExpr, which must evaluate to
a positive integer. Errors for 0, negative integers, and non-integers.
popcount(+IntExpr)
Return the number of 1s in the binary representation of the non-negative integer IntExpr.
getbit(+IntExprV, +IntExprI)
Evaluates to the bit value (0 or 1) of the IntExprI-th bit of IntExprV. Both arguments must eval-
uate to non-negative integers. The result is equivalent to (IntExprV >> IntExprI)/\1,
but more efficient because materialization of the shifted value is avoided. Future versions
will optimise (IntExprV >> IntExprI)/\1 to a call to getbit/2, providing both
portability and performance.82
seed(+Seed)
Set the seed of the random generator for this thread. Seed is an integer or the atom
random. If random, repeat the initialization procedure described with the function
random/1. Here is an example:
?- set_random(seed(111)), A is random(6).
A = 5.
81
The eval/1 function was first introduced by ECLiPSe and is under consideration for YAP.
82
This issue was fiercely debated at the ISO standard mailinglist. The name getbit was selected for compatibility with
ECLiPSe, the only system providing this support. Richard OKeefe disliked the name and argued that efficient handling of
the above implementation is the best choice for this functionality.
?- set_random(seed(111)), A is random(6).
A = 5.
state(+State)
Set the generator to a state fetched using the state property of random property/1.
Using other values may lead to undefined behaviour.83
random property(?Option)
True when Option is a current property of the random generator. Currently, this predicate
provides access to the state. This predicate is not present on systems where the state is
inaccessible.
state(-State)
Describes the current state of the random generator. State is a normal Prolog term that can
be asserted or written to a file. Applications should make no other assumptions about its
representation. The only meaningful operation is to use as argument to set random/1
using the state(State) option.84
?- current_arithmetic_function(sin(_)).
true.
is list(+Term)
True if Term is bound to the empty list ([]) or a term with functor [|]85 and arity 2 and
the second argument is a list.86 This predicate acts as if defined by the definition below on
acyclic terms. The implementation fails safely if Term represents a cyclic list.
is_list(X) :-
var(X), !,
fail.
is_list([]).
83
The limitations of the underlying (GMP) library are unknown, which makes it impossible to validate the State.
84
BUG: GMP provides no portable mechanism to fetch and restore the state. The current implementation works, but the
state depends on the platform. I.e., it is generally not possible to reuse the state with another version of GMP or on a CPU
with different datasizes or endian-ness.
85
The traditional list functor is the dot (.). This is still the case of the command line option --traditional is
given. See also section 5.1.
86
In versions before 5.0.1, is list/1 just checked for [] or [ | ] and proper list/1 had the role of the current
is list/1. The current definition conforms to the de facto standard. Assuming proper coding standards, there should
only be very few cases where a quick-and-dirty is list/1 is a good choice. Richard OKeefe pointed at this issue.
is_list([_|T]) :-
is_list(T).
This predicate fails if the tail of List is equivalent to Int (e.g., length(L,L)).89
Deeper nested elements of structures can be selected by using a list of keys for the Key argument.
The Order argument is described in the table below92
The sort is stable, which implies that, if duplicates are kept, the order of duplicates is not
changed. If duplicates are removed, only the first element of a sequence of duplicates appears
in Sorted.
This predicate supersedes most of the other sorting primitives, for example:
The following example sorts a list of rows, for example resulting from csv read file/2)
ascending on the 3th column and descending on the 4th column:
See also sort/2 (ISO), msort/2, keysort/2, predsort/3 and order by/2.
msort(+List, -Sorted)
Equivalent to sort/2, but does not remove duplicates. Raises a type error if List is a
cyclic list or not a list.
keysort(+List, -Sorted) [ISO]
Sort a list of pairs. List must be a list of Key-Value pairs, terms whose principal functor is (-)/2.
List is sorted on Key according to the standard order of terms (see section 4.7.1). Duplicates are
not removed. Sorting is stable with regard to the order of the Values, i.e., the order of multiple
elements that have the same Key is not changed.
The keysort/2 predicate is often used together with library pairs. It can be used to sort
lists on different or multiple criteria. For example, the following predicates sorts a list of atoms
according to their length, maintaining the initial order for atoms that have the same length.
:- use_module(library(pairs)).
sort_atoms_by_length(Atoms, ByLength) :-
map_list_to_pairs(atom_length, Atoms, Pairs),
keysort(Pairs, Sorted),
pairs_values(Sorted, ByLength).
92
For compatibility with ECLiPSe, the values <, =<, > and >= are allowed as synonyms.
?- State = count(2),
findnsols(State, I, between(1, 12, I), L),
nb_setarg(1, State, 5).
State = count(5), L = [1, 2] ;
State = count(5), L = [3, 4, 5, 6, 7] ;
State = count(5), L = [8, 9, 10, 11, 12].
2 ?- listing(foo).
foo(a, b, c).
foo(a, b, d).
foo(b, c, e).
foo(b, c, f).
foo(c, c, g).
true.
5 ?-
4.31 Forall
forall(:Cond, :Action) [semidet]
For all alternative bindings of Cond, Action can be proven. The example verifies that all arith-
metic statements in the given list are correct. It does not say which is wrong if one proves
wrong.
?- forall(member(Child-Parent, ChildPairs),
assertz(child_of(Child, Parent))).
...,
( Generator,
SideEffect,
fail
; true
)
If your intent is to create variable bindings, the forall/2 control structure is inadequate.
Possibly you are looking for maplist/2, findall/3 or foreach/2.
4.32.1 Writef
writef(+Atom) [deprecated]
Equivalent to writef(Atom, []). See writef/2 for details.
Note that \l, \nnn and \\ are interpreted differently when character escapes are in effect. See
section 2.15.1.
Escape sequences to include arguments from Arguments. Each time a % escape sequence is
found in Format the next argument from Arguments is formatted according to the specification.
%t
print/1 the next item (mnemonic: term)
%w
write/1 the next item
%q
writeq/1 the next item
%d Write the term, ignoring operators. See also
write term/2. Mnemonic: old Edinburgh
display/1
%p
print/1 the next item (identical to %t)
%n Put the next item as a character (i.e., it is a character code)
%r Write the next item N times where N is the second item
(an integer)
%s Write the next item as a String (so it must be a list of char-
acters)
%f Perform a ttyflush/0 (no items used)
%Nc Write the next item Centered in N columns
%Nl Write the next item Left justified in N columns
%Nr Write the next item Right justified in N columns. N is a
decimal number with at least one digit. The item must be
an atom, integer, float or string.
S = "Hello World"
4.32.2 Format
The format family of predicates is the most versatile and portable93 way to produce textual output.
format(+Format)
Defined as format(Format) :- format(Format, []).. See format/2 for de-
tails.
format(+Format, :Arguments)
Format is an atom, list of character codes, or a Prolog string. Arguments provides the arguments
required by the format specification. If only one argument is required and this single argument
is not a list, the argument need not be put in a list. Otherwise the arguments are put in a list.
Special sequences start with the tilde (), followed by an optional numeric argument, option-
ally followed by a colon modifier (:), 94 followed by a character describing the action to be
undertaken. A numeric argument is either a sequence of digits, representing a positive decimal
number, a sequence hcharacteri, representing the character code value of the character (only
useful for t) or a asterisk (*), in which case the numeric argument is taken from the next argu-
ment of the argument list, which should be a positive integer. E.g., the following three examples
all pass 46 (.) to t:
The colon modifier (e.g., :d) causes the number to be printed according to the locale of
the output stream. See section 4.23.
D Same as d, but makes large values easier to read by inserting a comma every three digits
left or right of the dot. This is the same as :d, but using the fixed English locale.
e Output next argument as a floating point number in exponential notation. The numeric
argument specifies the precision. Default is 6 digits. Exact representation depends on the
C library function printf(). This function is invoked with the format %.hprecisionie.
E Equivalent to e, but outputs a capital E to indicate the exponent.
f Floating point in non-exponential notation. The numeric argument defines the number of
digits right of the decimal point. If the colon modifier (:) is used, the float is formatted
using conventions from the current locale, which may define the decimal point as well as
grouping of digits left of the decimal point.
g Floating point in e or f notation, whichever is shorter.
G Floating point in E or f notation, whichever is shorter.
i Ignore next argument of the argument list. Produces no output.
I Emit a decimal number using Prolog digit grouping (the underscore, _). The argument
describes the size of each digit group. The default is 3. See also section 2.15.1. For
example:
?- A is 1<<100, format(10I, [A]).
1_2676506002_2822940149_6703205376
| Set a tab stop on the current position. If an argument is supplied set a tab stop on the
position of that argument. This will cause all ts to be distributed between the previous
and this tab stop.
+ Set a tab stop (as |) relative to the last tab stop or the beginning of the line if no tab
stops are set before the +. This constructs can be used to fill fields. The partial format
sequence below prints an integer right-aligned and padded with zeros in 6 columns. The
. . . sequences in the example illustrate that the integer is aligned in 6 columns regardless
of the remainder of the format specification.
format(...|0td6+..., [..., Integer, ...])
Example:
simple_statistics :-
<obtain statistics> % left to the user
format(tStatisticst72|nn),
format(Runtime: .t 2f34| Inferences: .t D72|n,
[RunT, Inf]),
....
will output
Statistics
?- format(atom(A), D, [1000000]).
A = 1,000,000
formatting rules described above are used. Char is either a character code or a one-character
atom, specifying the letter to be (re)defined. Head is a term, whose name and arity are used
to determine the predicate to call for the redefined formatting character. The first argument
to the predicate is the numeric argument of the format command, or the atom default if
no argument is specified. The remaining arguments are filled from the argument list. The
example below defines T to print a timestamp in ISO8601 format (see format time/3).
The subsequent block illustrates a possible call.
:- format_predicate(T, format_time(_Arg,_Time)).
format_time(_Arg, Stamp) :-
must_be(number, Stamp),
format_time(current_output, %FT%T%z, Stamp).
?- get_time(Now),
format(Now, it is Tn, [Now]).
Now, it is 2012-06-04T19:02:01+0200
Now = 1338829321.6620328.
The value lives on the Prolog (global) stack. This implies that lookup time is independent of the
size of the term. This is particularly interesting for large data structures such as parsed XML
documents or the CHR global constraint store.
They support both global assignment using nb setval/2 and backtrackable assignment using
b setval/2.
Only one value (which can be an arbitrary complex Prolog term) can be associated to a variable
at a time.
Their value cannot be shared among threads. Each thread has its own namespace and values for
global variables.
Currently global variables are scoped globally. We may consider module scoping in future
versions.
Both b setval/2 and nb setval/2 implicitly create a variable if the referenced name does
not already refer to a variable.
Global variables may be initialised from directives to make them available during the program
lifetime, but some considerations are necessary for saved states and threads. Saved states do not store
global variables, which implies they have to be declared with initialization/1 to recreate them
after loading the saved state. Each thread has its own set of global variables, starting with an empty
set. Using thread initialization/1 to define a global variable it will be defined, restored
after reloading a saved state and created in all threads that are created after the registration. Finally,
global variables can be initialised using the exception hook exception/3. The latter technique is
used by CHR (see chapter 8).
b setval(+Name, +Value)
Associate the term Value with the atom Name or replace the currently associated value with
Value. If Name does not refer to an existing global variable, a variable with initial value [] is
created (the empty list). On backtracking the assignment is reversed.
b getval(+Name, -Value)
Get the value associated with the global variable Name and unify it with Value. Note that this
unification may further instantiate the value of the global variable. If this is undesirable the
normal precautions (double negation or copy term/2) must be taken. The b getval/2
predicate generates errors if Name is not an atom or the requested variable does not exist.
nb setval(+Name, +Value)
Associates a copy of Value created with duplicate term/2 with the atom Name. Note that
this can be used to set an initial value other than [] prior to backtrackable assignment.
nb getval(+Name, -Value)
The nb getval/2 predicate is a synonym for b getval/2, introduced for compatibility
and symmetry. As most scenarios will use a particular global variable using either non-
backtrackable or backtrackable assignment, using nb getval/2 can be used to document
that the variable is non-backtrackable. Raises existence error(variable, Name) if the
variable does not exist. Alternatively, nb current/2 can used to query a global variable.
This version fails if the variable does not exist rather than raising an exception.
nb linkval(+Name, +Value)
Associates the term Value with the atom Name without copying it. This is a fast special-
purpose variation of nb setval/2 intended for expert users only because the semantics on
backtracking to a point before creating the link are poorly defined for compound terms. The
principal term is always left untouched, but backtracking behaviour on arguments is undone if
the original assignment was trailed and left alone otherwise, which implies that the history that
created the term affects the behaviour on backtracking. Consider the following example:
demo_nb_linkval :-
T = nice(N),
( N = world,
nb_linkval(myvar, T),
fail
; nb_getval(myvar, V),
writeln(V)
).
nb current(?Name, ?Value)
Enumerate all defined variables with their value. The order of enumeration is undefined. Note
that nb current/2 can be used as an alternative for nb getval/2 to request the value of
a variable and fail silently if the variable does not exists.
nb delete(+Name)
Delete the named global variable. Succeeds also if the named variable does not exist.
Unix If the system provides ioctl calls for this, these are used and tty size/2 properly
reflects the actual size after a user resize of the window. The ioctl is issued on teh
file descriptor associated with the user input stream. As a fallback, the system uses
tty get capability/3 using li and co capabilities. In this case the reported size
reflects the size at the first call and is not updated after a user-initiated resize of the termi-
nal.
Windows Getting the size of the terminal is provided for swipl-win.exe. The requested
value reflects the current size. For the multithreaded version the console that is associated
with the user input stream is used.
shell(+Command, -Status)
Execute Command on the operating system. Command is given to the Bourne shell (/bin/sh).
Status is unified with the exit status of the command.
On Windows, shell/[1,2] executes the command using the CreateProcess() API and waits
for the command to terminate. If the command ends with a & sign, the command is handed to
the WinExec() API, which does not wait for the new task to terminate. See also win exec/2
and win shell/2. Please note that the CreateProcess() API does not imply the Windows
command interpreter (cmd.exe and therefore commands that are built in the command inter-
preter can only be activated using the command interpreter. For example, a file can be compied
using the command below.
Note that many of the operations that can be achieved using the shell built-in commands can
easily be achieved using Prolog primitives. See make directory/1, delete file/1,
rename file/2, etc. The clib package provides filesex, implementing various high level
file operations such as copy file/2. Using Prolog primitives instead of shell commands
improves the portability of your program.
The library process provides process create/3 and several related primitives that sup-
port more fine-grained interaction with processes, including I/O redirection and management of
asynchronous processes.
getenv(+Name, -Value)
Get environment variable. Fails silently if the variable does not exist. Please note that environ-
ment variable names are case-sensitive on Unix systems and case-insensitive on Windows.
setenv(+Name, +Value)
Set an environment variable. Name and Value must be instantiated to atoms or integers. The en-
vironment variable will be passed to shell/[0-2] and can be requested using getenv/2.
They also influence expand file name/2. Environment variables are shared between
threads. Depending on the underlying C library, setenv/2 and unsetenv/1 may not be
thread-safe and may cause memory leaks. Only changing the environment once and before
starting threads is safe in all versions of SWI-Prolog.
unsetenv(+Name)
Remove an environment variable from the environment. Some systems lack the underlying
unsetenv() library function. On these systems unsetenv/1 sets the variable to the empty
string.
unix(+Command)
This predicate comes from the Quintus compatibility library and provides a partial imple-
mentation thereof. It provides access to some operating system features and unlike the name
suggests, is not operating system specific. Defined Commands are below.
system(+Command)
Equivalent to calling shell/1. Use for compatibility only.
shell(+Command)
Equivalent to calling shell/1. Use for compatibility only.
shell
Equivalent to calling shell/0. Use for compatibility only.
cd
Equivalent to calling working directory/2 to the expansion (see
expand file name/2) of . For compatibility only.
cd(+Directory)
Equivalent to calling working directory/2. Use for compatibility only.
argv(-Argv)
Unify Argv with the list of command line arguments provided to this Prolog run. Please
note that Prolog system arguments and application arguments are separated by --.
Integer arguments are passed as Prolog integers, float arguments and Prolog floating
point numbers and all other arguments as Prolog atoms. New applications should use the
Prolog flag argv. See also the Prolog flag argv.
A stand-alone program could use the following skeleton to handle command line argu-
ments. See also section 2.10.2.
main :-
current_prolog_flag(argv, Argv),
append(_PrologArgs, [--|AppArgs], Argv), !,
main(AppArgs).
?- win_registry_get_value(
HKEY_LOCAL_MACHINE/Software/SWI/Prolog,
fileExtension,
Ext).
Ext = pl
?- win_folder(personal, MyDocuments).
This predicate is available in the Windows port of SWI-Prolog starting from 6.3.8/6.2.6.
This predicate fails if Windows does not yet support the underlying primitives. These are
available in recently patched Windows 7 systems and later.
This predicate throws an acception if the provided path is invalid or the underlying Win-
dows API returns an error.
For human-oriented tasks, time can be broken into years, months, days, hours, minutes, seconds
and a timezone. Physicists prefer to have time in an arithmetic type representing seconds or frac-
tion thereof, so basic arithmetic deals with comparison and durations. An additional advantage of
the physicists approach is that it requires much less space. For these reasons, SWI-Prolog uses an
arithmetic type as its prime time representation.
Many C libraries deal with time using fixed-point arithmetic, dealing with a large but finite time
interval at constant resolution. In our opinion, using a floating point number is a more natural choice
as we can use a natural unit and the interface does not need to be changed if a higher resolution is
required in the future. Our unit of choice is the second as it is the scientific unit.98 We have placed
our origin at 1970-1-1T0:0:0Z for compatibility with the POSIX notion of time as well as with older
time support provided by SWI-Prolog.
Where older versions of SWI-Prolog relied on the POSIX conversion functions, the current im-
plementation uses libtai to realise conversion between time-stamps and calendar dates for a period of
10 million years.
TimeStamp
A TimeStamp is a floating point number expressing the time in seconds since the Epoch at
1970-1-1.
date(Y,M,D,H,Mn,S,Off,TZ,DST)
We call this term a date-time structure. The first 5 fields are integers expressing the year,
month (1..12), day (1..31), hour (0..23) and minute (0..59). The S field holds the seconds as a
floating point number between 0.0 and 60.0. Off is an integer representing the offset relative to
UTC in seconds, where positive values are west of Greenwich. If converted from local time
(see stamp date time/3), TZ holds the name of the local timezone. If the timezone is not
known, TZ is the atom -. DST is true if daylight saving time applies to the current time,
false if daylight saving time is relevant but not effective, and - if unknown or the timezone
has no daylight saving time.
date(Y,M,D)
Date using the same values as described above. Extracted using date time value/3.
time(H,Mn,S)
Time using the same values as described above. Extracted using date time value/3.
the data types. TimeZone describes the timezone for the conversion. It is one of local to
extract the local time, UTC to extract a UTC time or an integer describing the seconds west
of Greenwich.
?- date_time_stamp(date(2006,7,214,0,0,0,0,-,-), Stamp),
stamp_date_time(Stamp, D, 0),
date_time_value(date, D, Date).
Date = date(2007, 1, 30)
When computing a time stamp from a local time specification, the UTC offset (arg 7), TZ (arg 8)
and DST (arg 9) argument may be left unbound and are unified with the proper information.
The example below, executed in Amsterdam, illustrates this behaviour. On the 25th of March
at 01:00, DST does not apply. At 02.00, the clock is advanced by one hour and thus both 02:00
and 03:00 represent the same time stamp.
1 ?- date_time_stamp(date(2012,3,25,1,0,0,UTCOff,TZ,DST),
Stamp).
UTCOff = -3600,
TZ = CET,
DST = false,
Stamp = 1332633600.0.
2 ?- date_time_stamp(date(2012,3,25,2,0,0,UTCOff,TZ,DST),
Stamp).
UTCOff = -7200,
TZ = CEST,
DST = true,
Stamp = 1332637200.0.
3 ?- date_time_stamp(date(2012,3,25,3,0,0,UTCOff,TZ,DST),
Stamp).
UTCOff = -7200,
TZ = CEST,
DST = true,
Stamp = 1332637200.0.
Note that DST and offset calculation are based on the POSIX function mktime(). If mktime()
returns an error, a representation error dst is generated.
key value
year Calendar year as an integer
month Calendar month as an integer 1..12
day Calendar day as an integer 1..31
hour Clock hour as an integer 0..23
minute Clock minute as an integer 0..59
second Clock second as a float 0.0..60.0
utc offset Offset to UTC in seconds (positive is west)
time zone Name of timezone; fails if unknown
daylight saving Bool (true) if dst is in effect
date Term date(Y,M,D)
time Term time(H,M,S)
a The abbreviated weekday name according to the current locale. Use format time/4
for POSIX locale.
A The full weekday name according to the current locale. Use format time/4 for POSIX
locale.
b The abbreviated month name according to the current locale. Use format time/4 for
POSIX locale.
B The full month name according to the current locale. Use format time/4 for POSIX
locale.
c The preferred date and time representation for the current locale.
C The century number (year/100) as a 2-digit integer.
d The day of the month as a decimal number (range 01 to 31).
D Equivalent to %m/%d/%y. (For Americans only. Americans should note that in other
countries %d/%m/%y is rather common. This means that in an international context this
format is ambiguous and should not be used.)
e Like %d, the day of the month as a decimal number, but a leading zero is replaced by a
space.
E Modifier. Not implemented.
f Number of microseconds. The f can be prefixed by an integer to print the desired number
of digits. E.g., %3f prints milliseconds. This format is not covered by any standard, but
available with different format specifiers in various incarnations of the strftime() function.
F Equivalent to %Y-%m-%d (the ISO 8601 date format).
g Like %G, but without century, i.e., with a 2-digit year (00-99).
99
Descriptions taken from Linux Programmers Manual
G The ISO 8601 year with century as a decimal number. The 4-digit year corresponding to
the ISO week number (see %V). This has the same format and value as %y, except that if
the ISO week number belongs to the previous or next year, that year is used instead.
V The ISO 8601:1988 week number of the current year as a decimal number, range 01 to
53, where week 1 is the first week that has at least 4 days in the current year, and with
Monday as the first day of the week. See also %U and %W.
h Equivalent to %b.
H The hour as a decimal number using a 24-hour clock (range 00 to 23).
I The hour as a decimal number using a 12-hour clock (range 01 to 12).
j The day of the year as a decimal number (range 001 to 366).
k The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded
by a blank. (See also %H.)
l The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded
by a blank. (See also %I.)
m The month as a decimal number (range 01 to 12).
M The minute as a decimal number (range 00 to 59).
n A newline character.
O Modifier to select locale-specific output. Not implemented.
p Either AM or PM according to the given time value, or the corresponding strings for
the current locale. Noon is treated as pm and midnight as am.
P Like %p but in lowercase: am or pm or a corresponding string for the current locale.
r The time in a.m. or p.m. notation. In the POSIX locale this is equivalent to %I:%M:%S
%p.
R The time in 24-hour notation (%H:%M). For a version including the seconds, see %T
below.
s The number of seconds since the Epoch, i.e., since 1970-01-01 00:00:00 UTC.
S The second as a decimal number (range 00 to 60). (The range is up to 60 to allow for
occasional leap seconds.)
t A tab character.
T The time in 24-hour notation (%H:%M:%S).
u The day of the week as a decimal, range 1 to 7, Monday being 1. See also %w.
U The week number of the current year as a decimal number, range 00 to 53, starting with
the first Sunday as the first day of week 01. See also %V and %W.
w The day of the week as a decimal, range 0 to 6, Sunday being 0. See also %u.
W The week number of the current year as a decimal number, range 00 to 53, starting with
the first Monday as the first day of week 01.
x The preferred date representation for the current locale without the time.
X The preferred time representation for the current locale without the date.
y The year as a decimal number without a century (range 00 to 99).
The table below gives some format strings for popular time representations. RFC1123
is used by HTTP. The full implementation of http timestamp/2 as available from
http/http header is here.
http_timestamp(Time, Atom) :-
stamp_date_time(Time, Date, UTC),
format_time(atom(Atom),
%a, %d %b %Y %T GMT,
Date, posix).
Name Example
rfc 1123 Fri, 08 Dec 2006 15:29:44 GMT
Fri, 08 Dec 2006 15:29:44 +0000
iso 8601 2006-12-08T17:29:44+02:00
20061208T172944+0200
2006-12-08T15:29Z
2006-12-08
20061208
2006-12
2006-W49-5
2006-342
size(W, H)
Change the size of the window. W and H are expressed in character units.
position(X, Y)
Change the top-left corner of the window. The values are expressed in pixel units.
zorder(ZOrder)
Change the location in the window stacking order. Values are bottom, top, topmost
and notopmost. Topmost windows are displayed above all other windows.
show(Bool)
If true, show the window, if false hide the window.
activate
If present, activate the window.
win_insert_menu(&Application, &Help)
exists file(+File)
True if File exists and is a regular file. This does not imply the user has read and/or write
permission for the file. This is the same as access file(File, exist).
...,
file_directory_name(Path, Dir),
file_base_name(Path, File),
directory_file_path(Dir, File, Path2),
same_file(Path, Path2).
exists directory(+Directory)
True if Directory exists and is a directory. This does not imply the user has read, search or
write permission for the directory.
delete file(+File)
Remove File from the file system.
extensions(ListOfExtensions)
List of file extensions to try. Default is . For each extension,
absolute file name/3 will first add the extension and then verify the condi-
tions imposed by the other options. If the condition fails, the next extension on the list is
tried. Extensions may be specified both as .ext or plain ext.
relative to(+FileOrDir)
Resolve the path relative to the given directory or the directory holding the given
file. Without this option, paths are resolved relative to the working directory (see
working directory/2) or, if Spec is atomic and absolute file name/[2,3]
is executed in a directive, it uses the current source file as reference.
access(Mode)
Imposes the condition access file(File, Mode). Mode is one of read, write, append,
execute, exist or none. See also access file/2.
file type(Type)
Defines extensions. Current mapping: txt implies [], prolog implies [.pl,
], executable implies [.so, ], qlf implies [.qlf, ] and
directory implies []. The file type source is an alias for prolog for com-
patibility with SICStus Prolog. See also prolog file type/2. This predicate only
returns non-directories, unless the option file type(directory) is specified.
file errors(fail/error)
If error (default), throw an existence error exception if the file cannot be found.
If fail, stay silent.102
solutions(first/all)
If first (default), the predicate leaves no choice point. Otherwise a choice point will be
left and backtracking may yield more solutions.
expand(true/false)
If true (default is false) and Spec is atomic, call expand file name/2 followed
by member/2 on Spec before proceeding. This is a SWI-Prolog extension.
The Prolog flag verbose file search can be set to true to help debugging Prologs
search for files.
This predicate is derived from Quintus Prolog. In Quintus Prolog, the argument order was
absolute file name(+Spec, +Options, -Path). The argument order has been changed for
compatibility with ISO and SICStus. The Quintus argument order is still accepted.
predicate is intended to provide platform-independent checking for absolute paths. See also
absolute file name/2 and prolog to os filename/2.
temporary files. Base is used as part of the final filename. Portable applications should limit
themselves to alphanumeric characters.
Because it is possible to guess the generated filename, attackers may create the filesystem entry
as a link and possibly create a security issue. New code should use tmp file stream/3.
open_url(URL, In) :-
tmp_file_stream(text, File, Stream),
close(Stream),
process_create(curl, [-o, File, URL], []),
open(File, read, In),
delete_file(File). % Unix-only
Temporary files created using this call are removed if the Prolog process terminates gracefully.
Calling delete file/1 using FileName removes the file and removes the entry from the
administration of files-to-be-deleted.
make directory(+Directory)
Create a new directory (folder) on the filesystem. Raises an exception on failure. On Unix
systems, the directory is created with default permissions (defined by the process umask
setting).
delete directory(+Directory)
Delete directory (folder) from the filesystem. Raises an exception on failure. Please note that
in general it will not be possible to delete a non-empty directory.
chdir(+Path)
Compatibility predicate. New code should use working directory/2.
105
BUG: Some of the file I/O predicates use local filenames. Changing directory while file-bound streams are open causes
wrong results on telling/1, seeing/1 and current stream/3.
abort
Abort the Prolog execution and restart the top level. If the -t toplevel command line
option is given, this goal is started instead of entering the default interactive top level.
Aborting is implemented by throwing the reserved exception $aborted. This exception
can be caught using catch/3, but the recovery goal is wrapped with a predicate that prunes
the choice points of the recovery goal (i.e., as once/1) and re-throws the exception. This is
illustrated in the example below, where we press control-C and a.
?- catch((repeat,fail), E, true).
CAction (h for help) ? abort
% Execution Aborted
halt [ISO]
Terminate Prolog execution. This is the same as halt(0). See halt/1 for details.
halt(+Status) [ISO]
Terminate Prolog execution with Status. This predicate calls PL halt() which preforms the
following steps:
Reclaim memory.
5. Call exit(Status) to terminate the process
prolog
This goal starts the default interactive top level. Queries are read from the stream user input.
See also the Prolog flag history. The prolog/0 predicate is terminated (succeeds) by
typing the end-of-file character (typically control-D).
The following two hooks allow for expanding queries and handling the result of a query. These
hooks are used by the top level variable expansion mechanism described in section 2.8.
expand query(+Query, -Expanded, +Bindings, -ExpandedBindings)
Hook in module user, normally not defined. Query and Bindings represents the query read
from the user and the names of the free variables as obtained using read term/3. If this
predicate succeeds, it should bind Expanded and ExpandedBindings to the query and bindings
to be executed by the top level. This predicate is used by the top level (prolog/0). See also
expand answer/2 and term expansion/2.
expand answer(+Bindings, -ExpandedBindings)
Hook in module user, normally not defined. Expand the result of a successfully executed
top-level query. Bindings is the query < N ame >= hValuei binding list from the query.
ExpandedBindings must be unified with the bindings the top level should print.
trace
Start the tracer. trace/0 itself cannot be seen in the tracer. Note that the Prolog top level
treats trace/0 special; it means trace the next goal.
tracing
True if the tracer is currently switched on. tracing/0 itself cannot be seen in the tracer.
notrace
Stop the tracer. notrace/0 itself cannot be seen in the tracer.
guitracer
Installs hooks (see prolog trace interception/4) into the system that redirect tracing
information to a GUI front-end providing structured access to variable bindings, graphical
overview of the stack and highlighting of relevant source code.
noguitracer
Revert back to the textual tracer.
trace(+Pred)
Equivalent to trace(Pred, +all).
trace(+Pred, +Ports)
Put a trace point on all predicates satisfying the predicate specification Pred. Ports is a list
of port names (call, redo, exit, fail). The atom all refers to all ports. If the port is
preceded by a - sign, the trace point is cleared for the port. If it is preceded by a +, the trace
point is set.
The predicate trace/2 activates debug mode (see debug/0). Each time a port (of the 4-
port model) is passed that has a trace point set, the goal is printed as with trace/0. Unlike
trace/0, however, the execution is continued without asking for further information. Exam-
ples:
?- trace(hello). Trace all ports of hello with any arity in any mod-
ule.
?- trace(foo/2, +fail). Trace failures of foo/2 in any module.
?- trace(bar/1, -all). Stop tracing bar/1.
notrace(:Goal)
Call Goal, but suspend the debugger while Goal is executing. The current implementation cuts
the choice points of Goal after successful completion. See once/1. Later implementations
may have the same semantics as call/1.
debug
Start debugger. In debug mode, Prolog stops at spy and trace points, disables last-call optimi-
sation and aggressive destruction of choice points to make debugging information accessible.
Implemented by the Prolog flag debug.
Note that the min free parameter of all stacks is enlarged to 8 K cells if debugging is switched
off in order to avoid excessive GC. GC complicates tracing because it renames the GNNN
variables and replaces unreachable variables with the atom <garbage_collected>. Call-
ing nodebug/0 does not reset the initial free-margin because several parts of the top level and
debugger disable debugging of system code regions. See also set prolog stack/2.
nodebug
Stop debugger. Implemented by the Prolog flag debug. See also debug/0.
debugging
Print debug status and spy points on current output stream. See also the Prolog flag debug.
spy(+Pred)
Put a spy point on all predicates meeting the predicate specification Pred. See section 4.5.
nospy(+Pred)
Remove spy point from all predicates meeting the predicate specification Pred.
nospyall
Remove all spy points from the entire program.
leash(?Ports)
Set/query leashing (ports which allow for user interaction). Ports is one of +Name, -Name,
?Name or a list of these. +Name enables leashing on that port, -Name disables it and ?Name
succeeds or fails according to the current setting. Recognised ports are call, redo, exit,
fail and unify. The special shorthand all refers to all ports, full refers to all ports
except for the unify port (default). half refers to the call, redo and fail port.
visible(+Ports)
Set the ports shown by the debugger. See leash/1 for a description of the Ports specification.
Default is full.
unknown(-Old, +New)
Edinburgh-Prolog compatibility predicate, interfacing to the ISO Prolog flag unknown. Val-
ues are trace (meaning error) and fail. If the unknown flag is set to warning,
unknown/2 reports the value as trace.
style check(+Spec)
Modify/query style checking options. Spec is one of the terms below or a list of these.
Loading a file using load files/2 or one of its derived predicates reset the style checking
options to their value before loading the file, scoping the option to the remainder of the file and
all files loaded after changing the style checking.
singleton(true)
The predicate read clause/3 (used by the compiler to read source code) warns on
variables appearing only once in a term (clause) which have a name not starting with an
underscore. See section 2.15.1 for details on variable handling and warnings.
no effect(true)
This warning is generated by the compiler for BIPs (built-in predicates) that are inlined
by the compiler and for which the compiler can prove that they are meaningless. An
example is using ==/2 against a not-yet-initialised variable as illustrated in the example
below. This comparison is always false.
always_false(X) :-
X == Y,
write(Y).
var branches(false)
Verifies that if a variable is introduced in a branch and used after the branch, it is in-
troduced in all branches. This code aims at bugs following the skeleton below, where
p(Next) may be called with Next unbound.
p(Arg) :-
( Cond
-> Next = value1
; true
),
p(Next).
If a variable V is intended to be left unbound, one can use V= . This construct is removed
by the compiler and thus has no implications for the performance of your program.
This check was suggested together with semantic singleton checking. The SWI-Prolog
libraries contain about a hundred clauses that are triggered by this style check. Unlike
semantic singleton analysis, only a tiny fraction of these clauses proofed faulty. In most
cases, the branches failing to bind the variable fail or raise an exception or the caller
handles the case where the variable is unbound. The status of this style check is unclear. It
might be removed in the future or it might be enhanced with a deeper analysis to be more
precise.
atom(true)
The predicate read/1 and derived predicates produce an error message on quoted atoms
or strings with more than 6 unescaped newlines. Newlines may be escaped with \ or \c.
This flag also enables warnings on \hnewlinei followed by blank space in native mode.
See section 2.15.1. Note that the ISO standard does not allow for unescaped newlines in
quoted atoms.
discontiguous(true)
Warn if the clauses for a predicate are not together in the same source file. It is advised
to disable the warning for discontiguous predicates using the discontiguous/1
directive.
charset(false)
Warn on atoms and variable names holding non-ASCII characters that are not quoted.
See also section 2.15.1.
statistics
Display a table of system statistics on the stream user error.
time(:Goal)
Execute Goal just like call/1 and print time used, number of logical inferences and the
average number of lips (logical inferences per second). Note that SWI-Prolog counts the actual
executed number of inferences rather than the number of passes through the call and redo ports
of the theoretical 4-port model. If Goal is non-deterministic, print statistics for each solution,
where the reported values are relative to the previous answer.
profile(:Goal)
Execute Goal just like once/1, collecting profiling statistics, and call show profile([]).
With XPCE installed this opens a graphical interface to examine the collected profiling data.
profile(:Goal, +Options)
Execute Goal just like once/1. Collect profiling statistics according to Options and call
show profile/1 with Options. The default collects CPU profiling and opens a graphical
interface when provided, printing the plain time usage of the top 25 predicates as a ballback.
Options are described below. Remaining options are passed to show profile/1.
time(+Which)
If Which is cpu (default), collect CPU timing statistics. If wall, collect wall time
statistics based on a 5 millisecond sampling rate. Wall time statistics can be useful if Goal
calls blocking system calls.
show profile(+Options)
This predicate first calls prolog:show profile hook/1. If XPCE is loaded, this hook is used to
107
There are two implementations; one based on setitimer() using the SIGPROF signal and one using Windows Multi
Media (MM) timers. On other systems the profiler is not provided.
Table 4.3: Keys for statistics/2. Space is expressed in bytes. Time is expressed in seconds,
represented as a floating point number.
activate a GUI interface to visualise the profile results. If not, a report is printed to the terminal
according to Options:
top(+N)
Show the only top N predicates. Default is 25.
cumulative(+Bool)
If true (default false), include the time spent in children in the time reported for a
predicate.
profiler(-Old, +New)
Query or change the status of the profiler. The status is one of
false
The profiler is not activated.
cputime
The profiler collects CPU statistics.
walltime
The profiler collects wall time statistics.
The value true is accepted as a synonym for cputime for compatibility reasons.
reset profiler
Switches the profiler to false and clears all collected statistics.
noprofile(+Name/+Arity, . . . )
Declares the predicate Name/Arity to be invisible to the profiler. The time spent in the named
predicate is added to the caller, and the callees are linked directly to the caller. This is
particularly useful for simple meta-predicates such as call/1, ignore/1, catch/3, etc.
Figure 4.1: Execution profiler showing the activity of the predicate chat:inv map list/5.
samples
Number of times the call-tree was sampled for collecting time statistics. On most hardware, the
resolution of SIGPROF is 1/100 second. This number must be sufficiently large to get reliable
timing figures. The Time menu allows viewing time as samples, relative time or absolute time.
sec
Total user CPU time with the profiler active.
predicates
Total count of predicates that have been called at least one time during the profile.
nodes
Number of nodes in the call-tree.
distortion
How much of the time is spent building the call-tree as a percentage of the total execution time.
Timing samples while the profiler is building the call-tree are not added to the call-tree.
The last part of the profiler collects statistics on the CPU time used in each node. On systems
providing setitimer() with SIGPROF, it ticks the current node of the call-tree each time the timer
fires. On Windows, a MM-timer in a separate thread checks 100 times per second how much time is
spent in the profiled thread and adds this to the current node. See section 4.41.3 for details.
loop :-
generator,
trim_stacks,
potentially_expensive_operation,
stop_condition, !.
The Prolog top-level loop is written this way, reclaiming memory resources after every user
query.
108
We hereby acknowledge Lionel Fourquaux, who suggested the design described here after a newsnet enquiry.
?- set_prolog_stack(global, limit(2*10**9)).
limit(+Bytes)
Set the limit to which the stack is allowed to grow. If the specified value is lower than the
current usage a permission error is raised. If the limit is larger than supported, the
system silently reduces the requested limit to the system limit.
min free(+Cells)
Minimum amount of free space after trimming or shifting the stack. Setting this value
higher can reduce the number of garbage collections and stack-shifts at the cost of higher
memory usage. The spare stack amount is reported and specified in cells. A cell is 4
bytes in the 32-bit version and 8 bytes on the 64-bit version. See address bits. See
also trim stacks/0 and debug/0.
spare(+Cells)
All stacks trigger overflow before actually reaching the limit, so the resulting error can be
handled gracefully. The spare stack is used for print message/2 from the garbage
collector and for handling exceptions. The default suffices, unless the user redefines
related hooks. Do not specify large values for this because it reduces the amount of
memory available for your real task.
Related hooks are message hook/3 (redefining GC messages),
prolog trace interception/4 and prolog exception hook/4.
109
This interface is contributed by Don Dwiggins.
C = 0
2 ?- dde_request(0, groups, X)
4 ?- close_dde_conversation(0).
true.
For details on interacting with progman, use the SDK online manual section on the Shell DDE
interface. See also the Prolog library(progman), which may be used to write simple Windows
setup scripts in Prolog.
of the DDE server can handle some more primitives, so if you need features not provided by this
interface, please study library(dde).
Service is the name of the DDE service provided (like progman in the client example above).
Topic is either an atom, indicating Goal only handles requests on this topic, or a variable that
also appears in Goal. Item and Value are variables that also appear in Goal. Item represents the
request data as a Prolog atom.110
The example below registers the Prolog current prolog flag/2 predicate to be accessi-
ble from other applications. The request may be given from the same Prolog as well as from
another application.
?- dde_register_service(prolog(current_prolog_flag, F, V),
current_prolog_flag(F, V)).
Home = /usr/local/lib/pl-2.0.6/
Handling DDE execute requests is very similar. In this case the template is of the form:
+Service(+Topic, +Item)
Passing a Value argument is not needed as execute requests either succeed or fail. If Goal
fails, a not processed is passed back to the caller of the DDE request.
4.44 Miscellaneous
dwim match(+Atom1, +Atom2)
True if Atom1 matches Atom2 in the Do What I Mean sense. Both Atom1 and Atom2 may
also be integers or floats. The two atoms match if:
Example:
?- wildcard_match([a-z]*.{pro,pl}[%], a_hello.pl%).
true.
sleep(+Time)
Suspend execution Time seconds. Time is either a floating point number or an integer. Gran-
ularity is dependent on the systems timer granularity. A negative time causes the timer to
return immediately. On most non-realtime operating systems we can only ensure execution is
suspended for at least Time seconds.
On Unix systems the sleep/1 predicate is realised in order of preference by nanosleep(),
usleep(), select() if the time is below 1 minute, or sleep(). On Windows systems Sleep() is used.
?- atom([]).
false.
?- atomic([]).
true.
?- [] == [].
false.
?- [] == [].
true.
The cons operator for creating list cells has changed from the pretty atom . to the ugly atom
[|], so we can use the . for other purposes. See section 5.4.1.
This modification has minimal impact on typical Prolog code. It does affect foreign code (see sec-
tion 11) that uses the normal atom and compound term interface for manipulation lists. In most cases
this can be avoided by using the dedicated list functions. For convenience, the macros ATOM nil and
ATOM dot are provided by SWI-Prolog.h.
Another place that is affected is write canonical/1. Impact is minimized by using
the list syntax for lists. The predicates read term/2 and write term/2 support the option
dotlists(true), which causes read term/2 to read .(a,[]) as [a] and write term/2
to write [a] as .(a,[]).
Representing lists the conventional way using ./2 as cons-cell and [] as list terminator both (inde-
pendently) poses conflicts, while these conflicts are easily avoided.
Using ./2 prevents using this commonly used symbol as an operator because a.B cannot be
distinguished from [a|B]. Freeing ./2 provides us with a unique term that we can use for
functional notation on dicts as described in section 5.4.1.
Using [] as list terminator prevents dynamic distinction between atoms and lists. As a result,
we cannot use type polymorphism that involve both atoms and lists. For example, we cannot
use multi lists (arbitrary deeply nested lists) of atoms. Multi lists of atoms are in some situations
a good representation of a flat list that is assembled from sub sequences. The alternative, using
difference lists or DCGs is often less natural and sometimes demands for opening proper lists
(i.e., copying the list while replacing the terminating empty list with a variable) that have to be
added to the sequence. The ambiguity of atom and list is particularly painful when mapping
external data representations that do not suffer from this ambiguity.
At the same time, avoiding [] as a list terminator makes the various text representations
unambiguous, which allows us to write predicates that require a textual argument to accept both
atoms, strings, and lists of character codes or one-character atoms. Traditionally, the empty list
can be interpreted both as the string [] and .
?- write("Hello world!").
Hello world!
?- writeq("Hello world!").
"Hello world!"
Back quoted text (as in text) is mapped to a list of character codes in version 7. The settings for
the flags that control how double and back quoted text is read is summarised in table 5.1. Programs
that aim for compatibility should realise that the ISO standard defines back quoted text, but does not
define the back quotes Prolog flag and does not define the term that is produced by back quoted
text.
Section 5.2.4 motivates the introduction of strings and mapping double quoted text to this type.
Table 5.1: Mapping of double and back quoted text in the two modes.
If String does not represent a number, the predicate fails rather than throwing a syntax
error exception.
Leading white space and Prolog comments are not allowed.
Numbers may start with + or -.
It is not allowed to have white space between a leading + or - and the number.
Floating point numbers in exponential notation do not require a dot before exponent, i.e.,
"1e10" is a valid number.
% a simple split
?- split_string("a.b.c.d", ".", "", L).
L = ["a", "b", "c", "d"].
% Consider sequences of separators as a single one
?- split_string("/home//jan///nice/path", "/", "/", L).
L = ["home", "jan", "nice", "path"].
% split and remove white space
?- split_string("SWI-Prolog, 7.0", ",", " ", L).
L = ["SWI-Prolog", "7.0"].
% only remove leading and trailing white space
?- split_string(" SWI-Prolog ", "", "\s\t\n", L).
L = ["SWI-Prolog"].
In the typical use cases, SepChars either does not overlap PadChars or is equivalent to han-
dle multiple adjacent separators as a single (often white space). The behaviour with par-
tially overlapping sets of padding and separators should be considered undefined. See also
read string/5.
The predicate read string/5 called repeatedly on an input until Sep is -1 (end of file) is
equivalent to reading the entire file into a string and calling split string/4, provided that
SepChars and PadChars are not partially overlapping.2 Below are some examples:
% Read a line
read_string(Input, "\n", "\r", End, String)
% Read a line, stripping leading and trailing white space
read_string(Input, "\n", "\r\t ", End, String)
% Read upto , or ), unifying End with 0, or 0)
read_string(Input, ",)", "\t ", End, String)
Lists of character codes is what you need if you want to parse text using Prolog gram-
mar rules (DCGs, see phrase/3). Most of the text reading predicates (e.g.,
read line to codes/2) return a list of character codes because most applications need
to parse these lines before the data can be processed.
2
Behaviour that is fully compatible would requite unlimited look-ahead.
Atoms are identifiers. They are typically used in cases where identity comparison is the main oper-
ation and that are typically not composed nor taken apart. Examples are RDF resources (URIs
that identify something), system identifiers (e.g., Boeing 747), but also individual words
in a natural language processing system. They are also used where other languages would use
enumerated types, such as the names of days in the week. Unlike enumerated types, Prolog
atoms do not form not a fixed set and the same atom can represent different things in different
contexts.
Strings typically represents text that is processed as a unit most of the time, but which is not an
identifier for something. Format specifications for format/3 is a good example. Another
example is a descriptive text provided in an application. Strings may be composed and decom-
posed using e.g., string concat/3 and sub string/5 or converted for parsing using
string codes/2 or created from codes generated by a generative grammar rule, also using
string codes/2.
list strings
This predicate may be used to assess compatibility issues due to the representation of double
quoted text as string objects. See section 5.2 and section 5.2.4. To use it, load your program
into Prolog and run list strings/0. The predicate lists source locations of string objects
encountered in the program that are not considered safe. Such string need to be examined
manually, after which one of the actions below may be appropriate:
Rewrite the code. For example, change [X] = "a" into X = 0a.
If a particular module relies heavily on representing strings as lists of character code,
consider adding the following directive to the module. Note that this flag only applies to
the module in which it appears.
:- set_prolog_flag(double_quotes, codes).
Use a back quoted string (e.g., text). Note that this will not make your code run re-
gardless of the --traditional command line option and code exploiting this mapping
is also not portable to ISO compliant systems.
If the strings appear in facts and usage is safe, add a clause to the multifile predicate
check:string predicate/1 to silence list strings/0 on all clauses of that predicate.
If the strings appear as an argument to a predicate that can handle string objects, add a
clause to the multifile predicate check:valid string goal/1 to silence list strings/0.
check:string predicate(:PredicateIndicator)
Declare that PredicateIndicator has clauses that contain strings, but that this is safe. For ex-
ample, if there is a predicate help info/2, where the second argument contains a double
quoted string that is handled properly by the predicates of the applications help system, add
the following declaration to stop list strings/0 from complaining:
:- multifile check:string_predicate/1.
check:string_predicate(user:help_info/2).
:- multifile check:valid_string_goal/1.
check:valid_string_goal(system:format(_,S,_)) :- string(S).
It hides the conceptual difference between text and program symbols. Where content of text
often matters because it is used in I/O, program symbols are merely identifiers that match with
the same symbol elsewhere. Program symbols can often be consistently replaced, for example
to obfuscate or compact a program.
Atoms are globally unique identifiers. They are stored in a shared table. Volatile strings repre-
sented as atoms come at a significant price due to the required cooperation between threads for
creating atoms. Reclaiming temporary atoms using Atom garbage collection is a costly process
that requires significant synchronisation.
Many Prolog systems (not SWI-Prolog) put severe restrictions on the length of atoms or the
maximum number of atoms.
Representing text as a list of character codes or 1-character atoms also comes at a price:
It is not possible to distinguish (at runtime) a list of integers or atoms from a string. Sometimes
this information can be derived from (implicit) typing. In other cases the list must be embedded
in a compound term to distinguish the two types. For example, s("hello world") could
be used to indicate that we are dealing with a string.
Lacking runtime information, debuggers and the toplevel can only use heuristics to decide
whether to print a list of integers as such or as a string (see portray text/1).
While experienced Prolog programmers have learned to cope with this, we still consider this an
unfortunate situation.
Lists are expensive structures, taking 2 cells per character (3 for SWI-Prolog in its current form).
This stresses memory consumption on the stacks while pushing them on the stack and dealing
with them during garbage collection is unnecessarilly expensive.
We observe that in many programs, most strings are only handled as a single unit during their life-
time. Examining real code tells us that double quoted strings typically appear in one of the following
roles:
A DCG literal Although represented as a list of codes is the correct representation for handling in
DCGs, the DCG translator can recognise the literal and convert it to the proper representation.
Such code need not be modified.
A format string This is a typical example of text that is conceptually not a program identifier. For-
mat is designed to deal with alternative representations of the format string. Such code need not
be modified.
Getting a character code The construct [X] = "a" is a commonly used template for getting the
character code of the letter a. ISO Prolog defines the syntax 0a for this purpose. Code using
this must be modified. The modified code will run on any ISO compliant processor.
As argument to list predicates to operate on strings Here, we see code such as
append("name:", Rest, Codes). Such code needs to be modi-
fied. In this particular example, the following is a good portable alternative:
phrase("name:", Codes, Rest)
Checks for a character to be in a set Such tests are often performed with code such as this:
memberchk(C, "!@#$"). This is a rather inefficient check in a traditional Prolog sys-
tem because it pushes a list of character codes cell-by-cell the Prolog stack and then traverses
this list cell-by-cell to see whether one of the cells unifies with C. If the test is successful, the
string will eventually be subject to garbage collection. The best code for this is to write a predi-
cate as below, which pushes noting on the stack and performs an indexed lookup to see whether
the character code is in my class.
my_class(0).
my_class(0!).
...
An alternative to reach the same effect is to use term expansion to create the clauses:
term_expansion(my_class(_), Clauses) :-
findall(my_class(C),
string_code(_, "!@#$", C),
Clauses).
my_class(_).
Finally, the predicate string code/3 can be exploited directly as a replacement for the
memberchk/2 on a list of codes. Although the string is still pushed onto the stack, it is more
compact and only a single entity.
...,
functor(Specific, Name, Arity),
functor(General, Name, Arity),
...,
Replacement of =../2 by compound name arguments/3 is typically needed to deal with code
that follow the skeleton below.
...,
Term0 =.. [Name|Args0],
maplist(convert, Args0, Args),
Term =.. [Name|Args],
...,
3
We believe that most users expect an operator declaration to define a new token, which would explain why the operator
name is often quoted in the declaration, but not while the operator is used. We are afraid that allowing for this easily creates
ambiguous syntax. Also, many development environments are based on tokenization. Having dynamic tokenization due to
operator declarations would make it hard to support Prolog in such editors.
4
Suggested by Joachim Schimpf.
5
https://groups.google.com/d/msg/comp.lang.prolog/ozqdzI-gi_g/2G16GYLIS0IJ
For predicates, goals and arithmetic functions (evaluable terms), hnamei and hnamei() are equivalent.
Below are some examples that illustrate this behaviour.
?- go().
Hello world
?- go.
Hello world
?- Pi is pi().
Pi = 3.141592653589793.
?- Pi is pi.
Pi = 3.141592653589793.
Note that the cannonical representation of predicate heads and functions without arguments is an
atom. Thus, clause(go(), Body) returns the clauses for go/0, but clause(-Head, -Body, +Ref)
unifies Head with an atom if the clause specified by Ref is part of a predicate with zero arguments.
[]
This operator is typically declared as a low-priority yf postfix operator, which allows for
array[index] notation. This syntax produces a term []([index],array).
{}
This operator is typically declared as a low-priority xf postfix operator, which
allows for head(arg) { body } notation. This syntax produces a term
{}({body},head(arg)).
Below is an example that illustrates the representation of a typical curly bracket language in
Prolog.
?- displayq(func(arg)
6
Introducing block operators was proposed by Jose Morales. It was discussed in the Prolog standardization mailing list,
but there were too many conflicts with existing extensions (ECLiPSe and B-Prolog) and doubt about their need to reach an
agreement. Increasing need to get to some solution resulted in what is documented in this section. These extensions are also
implemented in recent versions of YAP.
{ a[10] = 5;
update();
}).
{}({;(=([]([10],a),5),;(update()))},func(arg))
A dict can not hold duplicate keys. The dict is transformed into an opaque internal representation
that does not respect the order in which the key-value pairs appear in the input text. If a dict is
written, the keys are written according to the standard order of terms (see section 4.7.1). Here are
some examples, where the second example illustrates that the order is not maintained and the third
illustrates an anonymous dict.
?- A = point{x:1, y:2}.
A = point{x:1, y:2}.
?- A = point{y:2, x:1}.
A = point{x:1, y:2}.
?- A = _{first_name:"Mel", last_name:"Smith"}.
A = _G1476{first_name:"Mel", last_name:"Smith"}.
Dicts can be unified following the standard symmetric Prolog unification rules. As dicts use an internal
canonical form, the order in which the named keys are represented is not relevant. This behaviour is
illustrated by the following example.
Note In the current implementation, two dicts unify only if they have the same set of keys and the tags
and values associated with the keys unify. In future versions, the notion of unification between dicts
could be modified such that two dicts unify if their tags and the values associated with common keys
unify, turning both dicts into a new dict that has the union of the keys of the two original dicts.
?- X = point{x:1,y:2}.x.
X = 1.
?- Pt = point{x:1,y:2}, write(Pt.y).
2
Pt = point{x:1,y:2}.
?- X = point{x:1,y:2}.C.
X = 1,
C = x ;
X = 2,
C = y.
The compiler translates a goal that contains ./2 terms in its arguments into a conjunction of calls to
./3 defined in the system module. Terms functor.2 that appears in the head are replaced with a
variable and calls to ./3 are inserted at the start of the body. Below are two examples, where the
first extracts the x key from a dict and the second extends a dict containing an address with the postal
code, given a find postal code/4 predicate.
dict_x(X, X.x).
Note that expansion of ./2 terms implies that such terms cannot be created by writing them
explicitly in your source code. Such terms can still be created with functor/3, =../2,
compound name arity/3 and compound name arguments/3.7
Functions are normal Prolog predicates. The dict infrastructure provides a more convenient syntax
for representing the head of such predicates without worrying about the argument calling conventions.
The code below defines a function multiply(Times) on a point that creates a new point by multi-
plying both coordinates. and len8 to compute the length from the origin. The . and := operators
are used to abstract the location of the predicate arguments. It is allowed to define multiple a function
with multiple clauses, providing overloading and non-determinism.
:- module(point, []).
M.len() := Len :-
Len is sqrt(M.x**2 + M.y**2).
?- X = point{x:1, y:2}.multiply(2).
X = point{x:2, y:4}.
?- X = point{x:1, y:2}.multiply(2).len().
X = 4.47213595499958.
get(?Key)
Same as Dict.Key, but maps to get dict/3 instead of get dict ex/3. This implies that
the function evaluation fails silently if Key does not appear in Dict. See also :</2, which can
be used to test for existence and unify multiple key values from a dict. For example:
?- write(t{a:x}.get(a)).
x
?- write(t{a:x}.get(b)).
false.
8
as length would result in a predicate length/2, this name cannot be used. This might change in future versions.
put(+New)
Evaluates to a new dict where the key-values in New replace or extend the key-values in the
original dict. See put dict/3.
put(+KeyPath, +Value)
Evaluates to a new dict where the KeyPath-Value replaces or extends the key-values in the
original dict. KeyPath is either a key or a term KeyPath/Key,9 replacing the value associated
with Key in a sub-dict of the dict on which the function operates. See put dict/4. Below
are some examples:
?- A = _{}.put(a, 1).
A = _G7359{a:1}.
?- A = _{a:1}.put(a, 2).
A = _G7377{a:2}.
?- A = _{a:1}.put(b/c, 2).
A = _G1395{a:1, b:_G1584{c:2}}.
?- A = _{a:_{b:1}}.put(a/b, 2).
A = _G1429{a:_G1425{b:2}}.
?- A = _{a:1}.put(a/b, 2).
A = _G1395{a:_G1578{b:2}}.
is dict(@Term)
True if Term is a dict. This is the same as is dict(Term, ).
is dict(@Term, -Tag)
True if Term is a dict of Tag.
?- A = point{x:1, y:2}.put(_{x:3}).
A = point{x:3, y:2}.
?- A = point{x:1, y:2}.put([x=3]).
A = point{x:3, y:2}.
?- A = point{x:1, y:2}.put([x=3,z=0]).
A = point{x:3, y:2, z:0}.
plot(Dict, On) :-
_{x:X, y:Y, z:Z} :< Dict, !,
plot_xyz(X, Y, Z, On).
plot(Dict, On) :-
_{x:X, y:Y} :< Dict, !,
plot_xy(X, Y, On).
See also select dict/2 to ignore Rest and >:</2 for a symmetric partial unification of
two dicts.
member(Dict, List),
Dict >:< point{x:0, y:Y}.
Compound terms Compound terms with positional arguments form the traditional way to package
data in Prolog. This representation is well understood, fast and compound terms are stored
efficiently. Compound terms are still the representation of choice, provided that the number of
arguments is low and fixed or compactness or performance are of utmost importance.
A good example of a compound term is the representation of RDF triples using the term
rdf(Subject, Predicate, Object) because RDF triples are defined to have precisely these three
arguments and they are always referred to in this order. An application processing information
about persons should probably use dicts because the information that is related to a person is not
so fixed. Typically we see first and last name. But there may also be title, middle name, gender,
date of birth, etc. The number of arguments becomes unmanagable when using a compound
term, while adding or removing an argument leads to many changes in the program.
Library record Using library record relieves the maintenance issues associated with using com-
pound terms significantly. The library generates access and modification predicates for each
field in a compound term from a declaration. The library provides sound access to compound
terms with many arguments. One of its problems is the verbose syntax needed to access or
modify fields which results from long names for the generated predicates and the restriction
that each field needs to be extracted with a separate goal. Consider the example below, where
the first uses library record and the second uses dicts.
...,
person_first_name(P, FirstName),
person_last_name(P, LastName),
format(Dear w w,nn, [FirstName, LastName]).
...,
format(Dear w w,nn, [Dict.first_name, Dict.last_name]).
Records have a fixed number of arguments and (non-)existence of an argument must be rep-
resented using a value that is outside the normal domain. This lead to unnatural code. For
example, suppose our person also has a title. If we know the first name we use this and else we
use the title. The code samples below illustrate this.
salutation(P) :-
person_first_name(P, FirstName), nonvar(FirstName), !,
person_last_name(P, LastName),
format(Dear w w,nn, [FirstName, LastName]).
salutation(P) :-
person_title(P, Title), nonvar(Title), !,
person_last_name(P, LastName),
format(Dear w w,nn, [Title, LastName]).
salutation(P) :-
_{first_name:FirstName, last_name:LastName} :< P, !,
format(Dear w w,nn, [FirstName, LastName]).
salutation(P) :-
_{title:Title, last_name:LastName} :< P, !,
format(Dear w w,nn, [Title, LastName]).
Library assoc This library implements a balanced binary tree. Dicts can replace the use of this
library if the association is fairly static (i.e., there are few update operations), all keys are atoms
or (small) integers and the code does not rely on ordered operations.
Library option Option lists are introduced by ISO Prolog, for example for read term/3,
open/4, etc. The option library provides operations to extract options, merge options lists,
etc. Dicts are well suited to replace option lists because they are cheaper, can be processed
faster and have a more natural syntax.
Library pairs This library is commonly used to process large name-value associations. In many
cases this concerns short-lived datastructures that result from findall/3, maplist/3 and
similar list processing predicates. Dicts may play a role if frequent random key lookups
are needed on the resulting association. For example, the skeleton create a pairs list, use
list to assoc/2 to create an assoc, followed by frequent usage of get assoc/3 to ex-
tract key values can be replaced using dict pairs/3 and the dict access functions. Using
dicts in this scenario is more efficient and provides a more pleasant access syntax.
Using compound terms with library record, which generates access predicates for a term
using positional arguments from a description.
Using library assoc which represents the associations as a balanced binary tree.
This situation is unfortunate. Each of these have their advantages and disadvantages. E.g., com-
pound terms are compact and fast, but inflexible and using positional arguments quickly breaks down.
Library record fixes this, but the syntax is considered hard to use. Lists are flexible, but expensive
and the alternative key-value representations that are used complicate the matter even more. Library
assoc allows for efficient manipulation of changing associations, but the syntactical representation
of an assoc is complex, which makes them unsuitable for e.g., options lists as seen in predicates such
as open/4.
The attribute list of the element(Name, Attributes, Content) will become a dict.
Attribute values will remain atoms
CDATA in element content will be represented as strings
Instead of using json(KeyValueList), the new interface will translate JSON objects to a dict.
The type of this dict will be json.
String values in JSON will be mapped to strings.
The values true, false and null will be represented as atoms.
Text representation Although strings resolve this issue for many applications, we are still faced
with the representation of text as lists of characters which we need for parsing using DCGs. The
ISO standard provides two representations, a list of character codes (codes for short) and a list
of one-character atoms (chars for short). There are two sets of predicates, named * code(s) and
* char(s) that provide the same functionality (e.g., atom codes/2 and atom chars/2) using
their own representation of characters. Codes can be used in arithmetic expressions, while chars are
more readable. Neither can unambiguously be interpreted as a representation for text because codes
can be interpreted as a list of integers and chars as a list of atoms.
We have not found a convincing way out. One of the options could be the introduction of a char
type. This type can be allowed in arithmetic and with the 0char syntax we have a concrete syntax
for it.
Arrays Although lists are generally a much cleaner alternative for Prolog, real arrays with direct
access to elements can be useful for particular tasks. The problem of integrating arrays is twofold.
First of all, there is no good one-size-fits-all data representation for arrays. Many tasks that involve
arrays require mutable arrays, while Prolog data is immutable by design. Second, standard Prolog
has no good syntax support for arrays. SWI-Prolog version 7 has block operators (see section 5.3.3)
which can resolve the syntactic issues. Block operators have been adopted by YAP.
Lambda expressions Although many alternatives10 have been proposed, we still feel uneasy with
them.
Loops Many people have explored routes to avoid the need for recursion in Prolog for simple iter-
ations over data. ECLiPSe have proposed logical loops [Schimpf, 2002], while B-Prolog introduced
declarative loops and list comprehension11 . The above mentioned lambda expressions, combined with
maplist/2 can achieve similar results.
10
See e.g., http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord
11
http://www.probp.com/download/loops.pdf
of a module file, defining reverse/2 and hiding the helper predicate rev/3. A module can use all
built-in predicates and, by default, cannot redefine system predicates.
:- module(reverse, [reverse/2]).
reverse(List1, List2) :-
rev(List1, [], List2).
The module is named reverse. Typically, the name of a module is the same as the name of the file
by which it is defined without the filename extension, but this naming is not enforced. Modules are
organised in a single and flat namespace and therefore module names must be chosen with some care
to avoid conflicts. As we will see, typical applications of the module system rarely use the name of a
module explicitly in the source text.
:- module(+Module, +PublicList)
This directive can only be used as the first term of a source file. It declares the file to be
a module file, defining a module named Module. Note that a module name is an atom.
The module exports the predicates of PublicList. PublicList is a list of predicate indicators
(name/arity or name//arity pairs) or operator declarations using the format op(Precedence,
Type, Name). Operators defined in the export list are available inside the module as well as to
modules importing this module. See also section 4.25.
Compatible to Ciao Prolog, if Module is unbound, it is unified with the basename without
extension of the file being loaded.
:- use_module(library(dialect/LangOption)).
use module(+Files)
Load the file(s) specified with Files just like ensure loaded/1. The files must all be module
files. All exported predicates from the loaded files are imported into the module from which
this predicate is called. This predicate is equivalent to ensure loaded/1, except that it
raises an error if Files are not module files.
The imported predicates act as weak symbols in the module into which they are imported. This
implies that a local definition of a predicate overrides (clobbers) the imported definition. If the
flag warn override implicit import is true (default), a warning is printed. Below
is an example of a module that uses library(lists), but redefines flatten/2, giving it a totally
different meaning:
:- module(shapes, []).
:- use_module(library(lists)).
flatten(cube, square).
flatten(ball, circle).
Warning: /home/janw/Bugs/Import/t.pl:5:
Local definition of shapes:flatten/2
overrides weak import from lists
This warning can be avoided by (1) using use module/2 to only import the
predicates from the lists library that are actually used in the shapes mod-
ule, (2) using the except([flatten/2]) option of use module/2, (3)
use :- abolish(flatten/2). before the local definition or (4) setting
warn override implicit import to false. Globally disabling this warning is
only recommended if overriding imported predicates is common as a result of design choices
or the program is ported from a system that silently overrides imported predicates.
Note that it is always an error to import two modules with use module/1 that export the
same predicate. Such conflicts must be resolved with use module/2 as described above.
:- use_module(library(lists), [ member/2,
append/2 as list_concat
]).
:- use_module(library(option), except([meta_options/3])).
In most cases a module is imported because some of its predicates are being used. However,
sometimes a module is imported for other reasons, e.g., for its declarations. In such cases it is best
practice to use use module/2 with empty ImportList. This distinguishes an imported module that
is used, although not for its predicates, from a module that is needlessly imported.
The module/2, use module/1 and use module/2 directives are sufficient to partition a
simple Prolog program into modules. The SWI-Prolog graphical cross-referencing tool gxref/0
can be used to analyse the dependencies between non-module files and propose module declarations
for each file.
:- module(maplist, [maplist/3]).
:- meta_predicate maplist(2, ?, ?).
0..9
The argument is a term that is used to reference a predicate with N more arguments than
the given argument term. For example: call(0) or maplist(1, +).
:
The argument is module-sensitive, but does not directly refer to a predicate. For example:
consult(:).
-
The argument is not module-sensitive and unbound on entry.
?
The argument is not module-sensitive and the mode is unspecified.
*
The argument is not module-sensitive and the mode is unspecified. The specifica-
tion * is equivalent to ?. It is accepted for compatibility reasons. The predicate
predicate property/2 reports arguments declared using * with ?.
+
The argument is not module-sensitive and bound (i.e., nonvar) on entry.
This extension is used to denote the possibly -annotated goal of setof/3, bagof/3,
aggregate/3 and aggregate/4. It is processed similar to 0, but leaving the /2
intact.
//
The argument is a DCG body. See phrase/3.
Each argument that is module-sensitive (i.e., marked 0..9, : or ) is qualified with the context
module of the caller if it is not already qualified. The implementation ensures that the argument
is passed as hmodulei:htermi, where hmodulei is an atom denoting the name of a module and
htermi itself is not a :/2 term where the first argument is an atom. Below is a simple declaration
and a number of queries.
:- meta_predicate
meta(0, +).
meta(Module:Term, _Arg) :-
format(Module=w, Term = qn, [Module, Term]).
?- meta(test, x).
Module=user, Term = test
?- meta(m1:test, x).
Module=m1, Term = test
?- m2:meta(test, x).
Module=m2, Term = test
?- m1:meta(m2:test, x).
Module=m2, Term = test
?- meta(m1:m2:test, x).
Module=m2, Term = test
?- meta(m1:42:test, x).
Module=42, Term = test
The meta predicate/1 declaration is the portable mechanism for defining meta-predicates
and replaces the old SWI-Prolog specific mechanism provided by the deprecated predicates
module transparent/1, context module/1 and strip module/3. See also sec-
tion 6.15.
Note that the second example is the same due to the Prolog flag colon sets calling context.
The system predicate asserta/1 is called in the module world, which is possible because system
predicates are visible in all modules. At the same time, the calling context is set to world. Because
meta arguments are qualified with the calling context, the resulting call is the same as the first example.
@(:Goal, +Module)
Execute Goal, setting the calling context to Module. Setting the calling context affects meta-
predicates, for which meta arguments are qualified with Module and transparent predicates (see
module transparent/1). It has no implications for other predicates.
For example, the code asserta(done)@world is the same as asserta(world:done).
Unlike in world:asserta(done), asserta/1 is resolved in the current module rather
than the module world. This makes no difference for system predicates, but usually does make
a difference for user predicates.
Not that SWI-Prolog does not define @ as an operator. Some systems define this construct using
op(900, xfx, @).
module(+Module)
The call module(Module) may be used to switch the default working module for the inter-
active top level (see prolog/0). This may be used when debugging a module. The example
below lists the clauses of file of label/2 in the module tex.
1 ?- module(tex).
true.
tex: 2 ?- listing(file_of_label/2).
...
:- module(my_composite, []).
:- reexport([ module_1,
module_2,
module_3
]).
reexport(+Files)
Load and import predicates as use module/1 and re-export all imported predicates. The
reexport declarations must immediately follow the module declaration.
reexport(+File, +Import)
Import from File as use module/2 and re-export the imported predicates. The reexport
declarations must immediately follow the module declaration.
:- module(clpfd,
[ op(760, yfx, #<==>),
op(750, xfy, #==>),
op(750, yfx, #<==),
op(740, yfx, #\/),
...
(#<==>)/2,
(#==>)/2,
(#<==)/2,
(#\/)/2,
...
]).
In addition to built-in predicates, imported predicates and locally defined predicates, SWI-Prolog
modules can also call predicates from its import modules. Each module has a (possibly empty) list of
import modules. In the default setup, each new module has a single import module, which is user
for all normal user modules and system for all system library modules. Module user imports from
system where all built-in predicates reside. These special modules are described in more detail in
section 6.10.
The list of import modules can be manipulated and queried using the following predicates, as well
as using set module/1.
One usage scenario of import modules is to define a module that is a copy of another, but where
one or more predicates have an alternative definition.
export(+PredicateIndicator, . . . )
Add predicates to the public list of the context module. This implies the predicate will be
imported into another module if this module is imported with use module/[1,2]. Note
that predicates are normally exported using the directive module/2. export/1 is meant to
handle export from dynamically created modules.
import(+PredicateIndicator, . . . )
Import predicates PredicateIndicator into the current context module. PredicateIndicator must
specify the source module using the hmodulei:hpii construct. Note that predicates are normally
imported using one of the directives use module/[1,2]. The import/1 alternative
is meant for handling imports into dynamically created modules. See also export/1 and
export list/2.
?- assert(world_a:consistent),
set_prolog_flag(world_a:unknown, fail).
These calls create a module called world a and make the call world a:consistent succeed. Unde-
fined predicates will not raise an exception for this module (see unknown).
Import and export from a dynamically created world can be achieved using import/1 and
export/1 or by specifying the import module as described in section 6.9.
Each predicate of the program is assigned a module, called its definition module. The definition
module of a predicate is always the module in which the predicate was originally defined. Each active
goal in the Prolog system has a context module assigned to it.
The context module is used to find predicates for a Prolog term. By default, the context module
is the definition module of the predicate running the goal. For transparent predicates, however, this
is the context module of the goal inherited from the parent goal. Below, we implement maplist/3
using the transparent mechanism. The code of maplist/3 and maplist /3 is the same as in
section 6.4, but now we must declare both the main predicate and the helper as transparent to avoid
changing the context module when calling the helper.
:- module(maplist, maplist/3).
:- module_transparent
maplist/3,
maplist_/3.
Note that any call that translates terms into predicates is subject to the transparent mechanism, not
just the terms passed to module-sensitive arguments. For example, the module below counts the
number of unique atoms returned as bindings for a variable. It works as expected. If we use the
directive :- module transparent count atom results/3. instead, atom result/2
is called wrongly in the module calling count atom results/3. This can be solved using
strip module/3 to create a qualified goal and a non-transparent helper predicate that is defined in
the same module.
:- module(count_atom_results,
[ count_atom_results/3
]).
:- meta_predicate count_atom_results(-,0,-).
atom_result(Var, Goal) :-
call(Goal),
atom(Var).
:- module transparent(+Preds)
Preds is a comma-separated list of name/arity pairs (like dynamic/1). Each goal associated
with a transparent-declared predicate will inherit the context module from its parent goal.
context module(-Module)
Unify Module with the context module of the current goal. context module/1 itself is, of
course, transparent.
class(-Class)
True when Class is the class of the module. Defined classes are
user
Default for user-defined modules.
system
Module system and modules from hhomei/boot.
library
Other modules from the system directories.
temporary
Module is temporary.
test
Modules that create tests.
development
Modules that only support the development environment.
file(?File)
True if Module was loaded from File.
line count(-Line)
True if Module was loaded from the N-th line of file.
exports(-ListOfPredicateIndicators)
True if Module exports the given predicates. Predicate indicators are in canonical
form (i.e., always using name/arity and never the DCG form name//arity). Fu-
ture versions may also use the DCG form and include public operators. See also
predicate property/2.
exported operators(-ListOfOperators)
True if Module exports the given operators. Each exported operator is represented as a
term op(Pri,Assoc,Name).
program size(-Bytes)
Memory (in bytes) used for storing the predicates of this module. This figure includes
the predicate header and clauses. Future versions might give a more precise number,
including e.g., the clause index tables.
program space(-Bytes)
If present, this number limits the program size. See set module/1.
set module(:Property)
Modify properties of the module. Currently, the following properties may be modified:
base(+Base)
Set the default import module of the current module to Module. Typically, Module is one
of user or system. See section 6.9.
class(+Class)
Set the class of the module. See module property/2.
program space(+Bytes)
Maximum amount of memory used to store the predicates defined inside the module.
Raises a permission error if the current usage is above the requested limit. Setting the
limit to 0 (zero) removes the limit. An attempt to assert clauses that causes the limit to
be exceeded causes a resource error(program space) exception. See assertz/1
and module property/2.
Modules that provide meta-predicates for a module to be compiled must be loaded explicitly by
that module.
The meta-predicate directives of exported predicates must follow the module/2 directive im-
mediately.
After changing a meta-declaration, all modules that call the modified predicates need to be
recompiled.
If a module does not define a predicate, it is searched for in the import modules. By default, the
import module of any user-defined module is the user module. In turn, the user module im-
ports from the module system that provides all built-in predicates. The auto-import hierarchy
can be changed using add import module/3 and delete import module/2.
This mechanism can be used to realise a simple object-oriented system or a hierarchical module
system.
Operator declarations are local to a module and may be exported. In Quintus and SICStus
all operators are global. YAP and Ciao also use local operators. SWI-Prolog provides global
operator declarations from within a module by explicitly qualifying the operator name with the
user module. I.e., operators are inherited from the import modules (see above).
In addition, CHR (chapter 8) provides a general purpose constraint handling language to reason
over user-defined constraints.
A key advantage of constraints is their ability to combine all available information that is stated
about the entities you reason about, independent of the order in which you state it, and before the
actual search for solutions even begins. Using the available information to prune parts of the search
space is called constraint propagation, and it is performed automatically by the available constraint
solvers for their respective domains.
Among the most important and typical instances is CLP(FD), constraint logic programming
over integers. For example, using constraints, you can state in the most general way that a vari-
able X is an integer greater than 0. If, later, X is bound to a concrete integer, the constraint solver
automatically ensures this. If you in addition constrain X to integers less than 3, the constraint solver
combines the existing knowledge to infer that X is either 1 or 2 (see below). To obtain concrete values
for X, you can ask the solver to label X and produce 1 and 2 on backtracking. See section A.8.
?- use_module(library(clpfd)).
...
true.
?- X #> 0, X #< 3.
X in 1..2.
Contrast this with plain Prolog, which has no efficient means to deal with (integer) X > 0 and X < 3.
At best it could translate X > 0 to between(1, infinite, X) and a similar primitive for X < 3. If the
two are combined it has no choice but to generate and test over this infinite two-dimensional space.
Using constraints therefore makes your program more declarative in that it frees you from some
procedural aspects and limitations of Prolog.
When working with constraints, keep in mind the following:
As with plain Prolog, !/0 also destroys the declarative semantics of constraints. A cut after
a goal that is delayed may prematurely prune the search space, because the truth of delayed
goals is not yet established. There are several ways to avoid cuts in constraint logic programs,
retaining both generality and determinism of your programs. See for example zcompare/3.
All of the mentioned constraint solvers are implemented using the attributed variables interface
described in section 7.1. These are lower-level predicates that are mainly intended for library authors,
not for typical Prolog programmers.
:- module(domain,
[ domain/2 % Var, ?Domain
]).
:- use_module(library(ordsets)).
domain(X, Dom) :-
var(Dom), !,
get_attr(X, domain, Dom).
domain(X, List) :-
list_to_ord_set(List, Domain),
attr_unify_hook(Domain, Y) :-
( get_attr(Y, domain, Dom2)
-> ord_intersection(Domain, Dom2, NewDomain),
( NewDomain == []
-> fail
; NewDomain = [Value]
-> Y = Value
; put_attr(Y, domain, NewDomain)
)
; var(Y)
-> put_attr( Y, domain, Domain )
; ord_memberchk(Y, Domain)
).
attribute_goals(X) -->
{ get_attr(X, domain, List) },
[domain(X, List)].
The predicate domain/2 fetches (first clause) or assigns (second clause) the variable a domain,
a set of values the variable can be unified with. In the second clause, domain/2 first associates the
domain with a fresh variable (Y) and then unifies X to this variable to deal with the possibility that
X already has a domain. The predicate attr unify hook/2 (see below) is a hook called after a
variable with a domain is assigned a value. In the simple case where the variable is bound to a concrete
value, we simply check whether this value is in the domain. Otherwise we take the intersection of the
domains and either fail if the intersection is empty (first example), assign the value if there is only one
value in the intersection (second example), or assign the intersection as the new domain of the variable
(third example). The nonterminal attribute goals//1 is used to translate remaining attributes
to user-readable goals that, when called, reinstate these attributes or attributes that correspond to
equivalent constraints.
Implementing constraint solvers (chapter 7) is the most common, but not the only use case for
attributed variables: If you implement algorithms that require efficient destructive modifications, then
using attributed variables is often a more convenient and somewhat more declarative alternative for
setarg/3 and related predicates whose sharing semantics are harder to understand. In particular,
attributed variables make it easy to express graph networks and graph-oriented algorithms, since each
variable can store pointers to further variables in its attributes. In such cases, the use of attributed vari-
ables should be confined within a module that exposes its functionality via more declarative interface
predicates.
To be done The way in which this hook currently works makes the implementation of important
classes of constraint solvers impossible or at least extremely impractical. For increased gen-
erality and convenience, simultaneous unifications as in [X,Y]=[0,1] should be processed
sequentially by the Prolog engine, or a more general hook should be provided in the future. See
[Triska, 2016] for more information.
attribute goals(+Var) //
This nonterminal is the main mechanism in which residual constraints are obtained. It is called
in every module where it is defined, and Var has an attribute. Its argument is that variable.
In each module, attribute goals//1 must describe a list of Prolog goals that are
declaratively equivalent to the goals that caused the attributes of that module to be present and
in their current state. It is always possible to do this (since these attributes stem from such
goals), and it is the responsibility of constraint library authors to provide this mapping without
exposing any library internals. Ideally and typically, remaining relevant attributes are mapped
to pure and potentially simplified Prolog goals that satisfy both of the following:
They are declaratively equivalent to the constraints that were originally posted.
They use only predicates that are themselves exported and documented in the modules
they stem from.
The latter property ensures that users can reason about residual goals, and see for themselves
whether a constraint library behaves correctly. It is this property that makes it possible to
thoroughly test constraint solvers by contrasting obtained residual goals with expected answers.
This nonterminal is used by copy term/3, on which the Prolog top level relies to ensure the
basic invariant of pure Prolog programs: The answer is declaratively equivalent to the query.
Note that instead of defaulty representations, a Prolog list is used to represent residual goals.
This simplifies processing and reasoning about residual goals throughout all programs that need
this functionality.
project attributes(+QueryVars, +ResidualVars)
A hook that can be defined in each module to project constraints on newly introduced variables
back to the query variables. QueryVars is the list of variables occurring in the query and
ResidualVars is a list of variables that have attributes attached. There may be variables that
occur in both lists. If possible, project attributes/2 should change the attributes so
that all constraints are expressed as residual goals that refer only to QueryVars, while other
variables are existentially quantified.
attr portray hook(+AttValue, +Var) [deprecated]
Called by write term/2 and friends for each attribute if the option attributes(portray)
is in effect. If the hook succeeds the attribute is considered printed. Otherwise
Module = ... is printed to indicate the existence of a variable. This predicate is
deprecated because it cannot work with pure interface predicates like copy term/3. Use
attribute goals//1 instead to map attributes to residual goals.
del attrs(+Var)
If Var is an attributed variable, delete all its attributes. In all other cases, this predicate succeeds
without side-effects.
7.2 Coroutining
Coroutining allows us to delay the execution of Prolog goals until their truth can be safely decided.
Among the most important coroutining predicates is dif/2, which expresses disequality of terms
in a sound way. The actual test is delayed until the terms are sufficiently different, or have become
identical. For example:
?- dif(X, Y), X = a, Y = b.
X = a,
Y = b.
?- dif(X, Y), X = a, Y = a.
false.
There are also lower-level coroutining predicates that are intended as building blocks for higher-level
constraints. For example, we can use freeze/2 to define a variable that can only be assigned an
atom:
?- freeze(X, atom(X)), X = a.
X = a.
In this case, calling atom/1 earlier causes the whole query to fail:
?- atom(X), X = a.
false.
If available, domain-specific constraints should be used in such cases. For example, to state that a
variable can only assume even integers, use the CLP(FD) constraint #=/2:
?- X mod 2 #= 0.
X mod 2#=0.
Importantly, domain-specific constraints can apply stronger propagation by exploiting logical proper-
ties of their respective domains. For example:
?- X mod 2 #= 0, X in 1..3.
X = 2.
Remaining constraints, such as X mod 2#=0 in the example above, are called residual goals. They
are said to flounder, because their truth is not yet decided. Declaratively, the query is only true if all
residual goals are satisfiable. Use call residue vars/2 to collect all variables that are involved
in constraints.
dif(@A, @B)
The dif/2 predicate is a constraint that is true if and only if A and B are different terms. If
A and B can never unify, dif/2 succeeds deterministically. If A and B are identical, it fails
immediately. Finally, if A and B can unify, goals are delayed that prevent A and B to become
equal. It is this last property that makes dif/2 a more general and more declarative alternative
for \=/2 and related predicates.
This predicate behaves as if defined by dif(X, Y) :- when(?=(X,Y), X \== Y).
See also ?=/2. The implementation can deal with cyclic terms.
The dif/2 predicate is realised using attributed variables associated with the module dif. It
is an autoloaded predicate that is defined in the library dif.
freeze(+Var, :Goal)
Delay the execution of Goal until Var is bound (i.e. is not a variable or attributed variable).
If Var is bound on entry freeze/2 is equivalent to call/1. The freeze/2 pred-
icate is realised using an attributed variable associated with the module freeze. Use
frozen(Var, Goal) to find out whether and which goals are delayed on Var.
frozen(@Var, -Goal)
Unify Goal with the goal or conjunction of goals delayed on Var. If no goals are frozen on Var,
Goal is unified to true.
when(@Condition, :Goal)
Execute Goal when Condition becomes true. Condition is one of ?=(X, Y), nonvar(X),
ground(X), ,(Cond1, Cond2) or ;(Cond1, Cond2). See also freeze/2 and dif/2. The
implementation can deal with cyclic terms in X and Y.
The when/2 predicate is realised using attributed variables associated with the module when.
It is defined in the autoload library when.
1
The implementation of call residue vars/2 is completely redone in version 7.3.2 (7.2.1) after discussion with
Bart Demoen. The current implementation no longer performs full scans of the stacks. The overhead is proportional to the
number of attributed variables on the stack, dead or alive.
T. Schrijvers, and B. Demoen, The K.U.Leuven CHR System: Implementation and Applica-
tion, First Workshop on Constraint Handling Rules: Selected Contributions (Fruhwirth, T. and
Meister, M., eds.), pp. 15, 2004.
8.1 Introduction
Note that the guard of a rule may not contain any goal that binds a variable in the head of the rule with
a non-variable or with another variable in the head of the rule. It may, however, bind variables that do
not appear in the head of the rule, e.g. an auxiliary variable introduced in the guard.
8.2.2 Semantics
In this subsection the operational semantics of CHR in Prolog are presented informally. They do not
differ essentially from other CHR systems.
When a constraint is called, it is considered an active constraint and the system will try to apply
the rules to it. Rules are tried and executed sequentially in the order they are written.
A rule is conceptually tried for an active constraint in the following way. The active constraint
is matched with a constraint in the head of the rule. If more constraints appear in the head, they are
looked for among the suspended constraints, which are called passive constraints in this context. If
the necessary passive constraints can be found and all match with the head of the rule and the guard of
the rule succeeds, then the rule is committed and the body of the rule executed. If not all the necessary
passive constraints can be found, or the matching or the guard fails, then the body is not executed and
the process of trying and executing simply continues with the following rules. If for a rule there are
multiple constraints in the head, the active constraint will try the rule sequentially multiple times, each
time trying to match with another constraint.
This process ends either when the active constraint disappears, i.e. it is removed by some rule, or
after the last rule has been processed. In the latter case the active constraint becomes suspended.
A suspended constraint is eligible as a passive constraint for an active constraint. The other way
it may interact again with the rules is when a variable appearing in the constraint becomes bound to
either a non-variable or another variable involved in one or more constraints. In that case the constraint
is triggered, i.e. it becomes an active constraint and all the rules are tried.
Rule Types There are three different kinds of rules, each with its specific semantics:
simplification
The simplification rule removes the constraints in its head and calls its body.
propagation
The propagation rule calls its body exactly once for the constraints in its head.
simpagation
The simpagation rule removes the constraints in its head after the \ and then calls its body. It is
an optimization of simplification rules of the form:
Rule Names Naming a rule is optional and has no semantic meaning. It only functions as documen-
tation for the programmer.
passive(Identifier)
The constraint in the head of a rule Identifier can only match a passive constraint in that rule.
There is an abbreviated syntax for this pragma. Instead of:
:- chr_option(Option,Value).
and may appear in the file anywhere after the first constraints declaration.
Available options are:
:- chr_constraint foo/1.
:- chr_constraint bar/2, baz/3.
In its extended form, a constraint specifier is c(A1 ,...,An ) where c is the constraints func-
tor, n its arity and the Ai are argument specifiers. An argument specifier is a mode, optionally
followed by a type. Example:
:- chr_constraint get_value(+,?).
:- chr_constraint domain(?int, +list(int)),
alldifferent(?list(int)).
+
The corresponding argument of every occurrence of the constraint is always ground.
?
The corresponding argument of every occurrence of the constraint can have any instantiation,
which may change over time. This is the default value.
Types A type can be a user-defined type or one of the built-in types. A type comprises a (possibly
infinite) set of values. The type declaration for a constraint argument means that for every instance of
that constraint the corresponding argument is only ever bound to values in that set. It does not state
that the argument necessarily has to be bound to a value.
The built-in types are:
int
The corresponding argument of every occurrence of the constraint is an integer number.
dense int
The corresponding argument of every occurrence of the constraint is an integer that can be used
as an array index. Note that if this argument takes values in [0, n], the array takes O(n) space.
float
. . . a floating point number.
number
. . . a number.
natural
. . . a positive integer.
any
The corresponding argument of every occurrence of the constraint can have any type. This is
the default value.
:- chr type(+TypeDeclaration)
User-defined types are algebraic data types, similar to those in Haskell or the discriminated
unions in Mercury. An algebraic data type is defined using chr type/1:
If the type term is a functor of arity zero (i.e. one having zero arguments), it names a monomor-
phic type. Otherwise, it names a polymorphic type; the arguments of the functor must be distinct
type variables. The body term is defined as a sequence of constructor definitions separated by
semi-colons.
Each constructor definition must be a functor whose arguments (if any) are types. Discriminated
union definitions must be transparent: all type variables occurring in the body must also occur
in the type.
Here are some examples of algebraic data type definitions:
Each algebraic data type definition introduces a distinct type. Two algebraic data types that
have the same bodies are considered to be distinct types (name equivalence).
Constructors may be overloaded among different types: there may be any number of construc-
tors with a given name and arity, so long as they all have different types.
Aliases can be defined using ==. For example, if your program uses lists of lists of integers,
you can define an alias as follows:
Type Checking Currently two complementary forms of type checking are performed:
1. Static type checking is always performed by the compiler. It is limited to CHR rule heads and
CHR constraint calls in rule bodies.
Two kinds of type error are detected. The first is where a variable has to belong to two types.
For example, in the program:
:-chr_constraint abc(?foo).
:-chr_constraint def(?bar).
the variable X has to be of both type foo and bar. This is reported as a type clash error:
The second kind of error is where a functor is used that does not belong to the declared type.
For example in:
:- chr_constraint abc(?foo).
bar appears in the head of the rule where something of type foo is expected. This is reported
as:
:-chr_constraint abc(?foo).
?- abc(bar).
ERROR: Type error: foo expected, found bar
(CHR Runtime Type Error)
Dynamic type checking is weaker than static type checking in the sense that it only checks the
particular program execution at hand rather than all possible executions. It is stronger in the
sense that it tracks types throughout the whole program.
Note that it is enabled only in debug mode, as it incurs some (minor) runtime overhead.
8.3.3 Compilation
The SWI-Prolog CHR compiler exploits term expansion/2 rules to translate the constraint han-
dling rules to plain Prolog. These rules are loaded from the library chr. They are activated if the
compiled file has the .chr extension or after finding a declaration in the following format:
:- chr_constraint ...
It is advised to define CHR rules in a module file, where the module declaration is immediately
followed by including the library(chr) library as exemplified below:
:- chr_constraint ...
Using this style, CHR rules can be defined in ordinary Prolog .pl files and the operator definitions
required by CHR do not leak into modules where they might cause conflicts.
8.4 Debugging
The CHR debugging facilities are currently rather limited. Only tracing is currently available. To use
the CHR debugging facilities for a CHR file it must be compiled for debugging. Generating debug
info is controlled by the CHR option debug, whose default is derived from the SWI-Prolog flag
generate debug info. Therefore debug info is provided unless the -nodebug is used.
8.4.1 Ports
For CHR constraints the four standard ports are defined:
call
A new constraint is called and becomes active.
exit
An active constraint exits: it has either been inserted in the store after trying all rules or has
been removed from the constraint store.
fail
An active constraint fails.
redo
An active constraint starts looking for an alternative solution.
In addition to the above ports, CHR constraints have five additional ports:
wake
A suspended constraint is woken and becomes active.
insert
An active constraint has tried all rules and is suspended in the constraint store.
remove
An active or passive constraint is removed from the constraint store.
try
An active constraint tries a rule with possibly some passive constraints. The try port is entered
just before committing to the rule.
apply
An active constraint commits to a rule with possibly some passive constraints. The apply port
is entered just after committing to the rule.
8.4.2 Tracing
Tracing is enabled with the chr trace/0 predicate and disabled with the chr notrace/0 pred-
icate.
When enabled the tracer will step through the call, exit, fail, wake and apply ports,
accepting debug commands, and simply write out the other ports.
The following debug commands are currently supported:
a abort
f fail
? help h help
creep
Step to the next port.
skip
Skip to exit port of this call or wake port.
ancestors
Print list of ancestor call and wake ports.
nodebug
Disable the tracer.
break
Enter a recursive Prolog top level. See break/0.
abort
Exit to the top level. See abort/0.
fail
Insert failure in execution.
help
Print the above available debug options.
chr trace
Activate the CHR tracer. By default the CHR tracer is activated and deactivated automatically
by the Prolog predicates trace/0 and notrace/0.
chr notrace
Deactivate the CHR tracer. By default the CHR tracer is activated and deactivated automatically
by the Prolog predicates trace/0 and notrace/0.
chr leash(+Spec)
Define the set of CHR ports on which the CHR tracer asks for user intervention (i.e. stops).
Spec is either a list of ports as defined in section 8.4.1 or a predefined alias. Defined aliases
are: full to stop at all ports, none or off to never stop, and default to stop at the call,
exit, fail, wake and apply ports. See also leash/1.
8.5 Examples
Here are two example constraint solvers written in CHR.
The program below defines a solver with one constraint, leq/2/, which is a less-than-or-
equal constraint, also known as a partial order constraint.
:- module(leq,[leq/2]).
:- use_module(library(chr)).
:- chr_constraint leq/2.
reflexivity @ leq(X,X) <=> true.
antisymmetry @ leq(X,Y), leq(Y,X) <=> X = Y.
idempotence @ leq(X,Y) \ leq(X,Y) <=> true.
transitivity @ leq(X,Y), leq(Y,Z) ==> leq(X,Z).
When the above program is saved in a file and loaded in SWI-Prolog, you can call the leq/2
constraints in a query, e.g.:
?- leq(X,Y), leq(Y,Z).
leq(_G23837, _G23841)
leq(_G23838, _G23841)
leq(_G23837, _G23838)
true .
When the query succeeds, the SWI-Prolog top level prints the content of the CHR constraint
store and displays the bindings generated during the query. Some of the query variables may
have been bound to attributed variables, as you see in the above example.
:- module(dom,[dom/2]).
:- use_module(library(chr)).
:- chr_constraint dom(?int,+list(int)).
:- chr_type list(T) ---> [] ; [T|list(T)].
When the above program is saved in a file and loaded in SWI-Prolog, you can call the dom/2
constraints in a query, e.g.:
?- dom(A,[1,2,3]), dom(A,[3,4,5]).
A = 3.
Guard bindings
The check guard bindings option only turns invalid calls to unification into failure. In
SICStus this option does more: it intercepts instantiation errors from Prolog built-ins such as
is/2 and turns them into failure. In SWI-Prolog, we do not go this far, as we like to separate
concerns more. The CHR compiler is aware of the CHR code, the Prolog system, and the
programmer should be aware of the appropriate meaning of the Prolog goals used in guards and
bodies of CHR rules.
is transformed into
:- chr_constraint my_labeling/0.
Be sure to put this code after all other rules in your program! With my labeling/0 (or another
predicate name of your choosing) the labeling is initiated, rather than ECLiPSes chr labeling/0.
Set semantics
The CHR system allows the presence of identical constraints, i.e. multiple constraints with the
same functor, arity and arguments. For most constraint solvers, this is not desirable: it affects
efficiency and possibly termination. Hence appropriate simpagation rules should be added of
the form:
constraint\constraint <=> true
Multi-headed rules
Multi-headed rules are executed more efficiently when the constraints share one or more vari-
ables.
Finding Constraints
The find chr constraint/1 predicate is fairly expensive. Avoid it, if possible. If you
must use it, try to use it with an instantiated top-level constraint symbol.
Ambiguous type aliases You have defined two overlapping type aliases.
Illegal mode/type declaration You have used invalid syntax in a constraint declaration.
Constraint multiply defined There is more than one declaration for the same constraint.
Interactive applications
Interactive applications often need to perform extensive computation. If such computations are
executed in a new thread, the main thread can process events and allow the user to cancel the
ongoing computation. User interfaces can also use multiple threads, each thread dealing with
input from a distinct group of windows. See also section 9.7.
SWI-Prolog multithreading is based on the POSIX thread standard [Butenhof, 1997] used on most
popular systems except for MS-Windows. On Windows it uses the pthread-win32 emulation of POSIX
threads mixed with the Windows native API for smoother and faster operation. The SWI-Prolog thread
implementation has been discussed in the ISO WG17 working group and is largely addopted by YAP
and XSB Prolog.2
Id is the alias name if the option alias(name) is given. Otherwise it is a blob of type
thread. The anonymous blobs are subject to atom garbage collection. If a thread handle
is garbage collected and the thread is not detached, it is joined if it has already terminated (see
thread join/2) and detached otherwise (see thread detach/1).3 The thread identi-
fier blobs are printed as <thread>(I,Ptr), where I is the internal thread identifier and Ptr
is the unique address of the identifier. The I is accepted as input argument for all thread
APIs that accept a thread identifier for convenient interaction from the toplevel. See also
thread property/2.
Options is a list of options. The currently defined options are below. Stack size options can also
take the value inf or infinite, which is mapped to the maximum stack size supported by
the platform.
alias(AliasName)
Associate an alias name with the thread. This name may be used to refer to the thread
and remains valid until the thread is joined (see thread join/2).
at exit(:AtExit)
Register AtExit as using thread at exit/1 before entering the thread goal. Unlike
calling thread at exit/1 as part of the normal Goal, this ensures the AtExit is called.
Using thread at exit/1, the thread may be signalled or run out of resources before
thread at exit/1 is reached.
debug(+Bool)
Enable/disable debugging the new thread. If false (default true), the new thread is
created with the property debug(false) and debugging is disabled before the new thread
is started. The thread debugging predicates such as tspy/1 and tdebug/0 do not
signal threads with the debug property set to false.4
detached(Bool)
If false (default), the thread can be waited for using thread join/2.
thread join/2 must be called on this thread to reclaim all resources associated
with the thread. If 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 thread join/2
and thread detach/1.
If a detached thread dies due to failure or exception of the initial goal, the thread prints a
message using print message/2. If such termination is considered normal, the code
must be wrapped using ignore/1 and/or catch/3 to ensure successful completion.
inherit from(+ThreadId)
Inherit defaults from the given ThreadId instead of the calling thread.
This option was added to ensure that the thread pool manager (see
thread create in pool/4), which is created lazily, has a predictable state.
The following properties are inherited:
3
Up to version 7.3.23, anonymous thread handles were integers. Using integers did not allow for safe checking of the
threads status as the thread may have died and the handle may have been reused and did not allow for garbage collection to
take care of forgotten threads.
4
Currently, the flag is only used as a hint for the the various debugging primitives, i.e., the system does not really enforce
that the target thread stays in nodebug mode.
The Goal argument is copied to the new Prolog engine. This implies that 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.
thread self(-Id)
Get the Prolog thread identifier of the running thread. If the thread has an alias, the alias name
is returned.
true
The goal has been proven successfully.
false
The goal has failed.
5
Older versions used stack. This is still accepted as a synonym.
exception(Term)
The thread is terminated on an exception. See print message/2 to turn system
exceptions into readable messages.
exited(Term)
The thread is terminated on thread exit/1 using the argument Term.
thread detach(+Id)
Switch thread into detached state (see detached(Bool) option at thread create/3) at
runtime. Id is the identifier of the thread placed in detached state. This may be the result of
thread self/1.
One of the possible applications is to simplify debugging. Threads that are created as de-
tached leave no traces if they crash. For non-detached threads the status can be inspected using
thread property/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.
thread exit(+Term) [deprecated]
Terminates the thread immediately, leaving exited(Term) as result state for
thread join/2. If the thread has the attribute detached(true) it terminates, but its
exit status cannot be retrieved using thread join/2, making the value of Term irrelevant.
The Prolog stacks and C thread are reclaimed.
The current implementation does not guarantee proper releasing of all mutexes and proper
cleanup in setup call cleanup/3, etc. Please use the exception mechanism (throw/1)
to abort execution using non-standard control.
thread initialization(:Goal)
Run Goal when thread is started. This predicate is similar to initialization/1, but is
intended for initialization operations of the runtime stacks, such as setting global variables as
described in section 4.33. Goal is run on four occasions: at the call to this predicate, after
loading a saved state, on starting a new thread and on creating a Prolog engine through the C
interface. On loading a saved state, Goal is executed after running the initialization/1
hooks.
thread at exit(:Goal)
Run Goal just before releasing the thread resources. This is to be compared to at halt/1, but
only for the current thread. These hooks are run regardless of why the execution of the thread
has been completed. When these hooks are run, the return code is already available through
thread property/2 using the result of thread self/1 as thread identifier. Note that
there are two scenarios for using exit hooks. Using thread at exit/1 is typically used
if the thread creates a side-effect that must be reverted if the thread dies. Another scenario is
where the creator of the thread wants to be informed when the thread ends. That cannot be
guaranteed by means of thread at exit/1 because it is possible that the thread cannot be
created or dies almost instantly due to a signal or resource error. The at exit(Goal) option
of thread create/3 is designed to deal with this scenario.
thread setconcurrency(-Old, +New)
Determine the concurrency of the process, which is defined as the maximum number of con-
currently active threads. Active here means they are using CPU time. This option is provided
is thread(@Term)
True if Term is a handle to an existing thread.
alias(Alias)
Alias is the alias name of thread Id.
detached(Boolean)
Current detached status of the thread.
id(Integer)
Integer identifier for the thread. Can be used as argument to the thread predicates, but
applications must be aware that these references are reused.
status(Status)
Current status of the thread. Status is one of:
running
The thread is running. This is the initial status of a thread. Please note that threads
waiting for something are considered running too.
suspended
Only if the thread is an engine (see section 10). Indicates that the engine is currently
not associated with an OS thread.
false
The Goal of the thread has been completed and failed.
true
The Goal of the thread has been completed and succeeded.
exited(Term)
The Goal of the thread has been terminated using thread exit/1 with Term as
argument. If the underlying native thread has exited (using pthread exit()) Term is
unbound.
exception(Term)
The Goal of the thread has been terminated due to an uncaught exception (see
throw/1 and catch/3).
engine(Boolean)
If the thread is an engine (see chapter 10), Boolean is true. Othwerwise the property is
not present.
thread(ThreadId)
If the thread is an engine that is currently attached to a thread, ThreadId is the thread that
executes the engine.
system thread id(Integer)
Thread identifier used by the operating system for the calling thread. Not available on all
OSes. This is the same as the Prolog flag system thread id for the calling thread.
Access to the system thread identifier can, on some systems, be used to gain additional
control over or information about Prolog threads.
mutex statistics
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 of times the calling thread has to wait for the mutex.
Generally collision count is close to zero on single-CPU hardware.
message queue of itself, see 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 Term, the waiting threads are all sent a wake-up 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.7
deadline(+AbsTime)
The call fails (silently) if no space has become available before AbsTime. See
get time/1 for the representation of absolute time. If AbsTime is earlier then the
current time, thread send message/3 fails immediately. Both resolution and
maximum wait time is platform-dependent.8
timeout(+Time)
Time is a float or integer and specifies the maximum time to wait in seconds. This is a
relative-time version of the deadline option. If both options are provided, the earlier
time is effective.
If Time is 0 or 0.0, thread send message/3 examines the queue and sends the mes-
sage if space is availabel, but does not suspend if no space is available, failing immediately
instead.
If Time < 0, thread send message/3 fails immediately without sending the mes-
sage.
<thread 1>
thread_get_message(a(A)),
7
See the documentation for the POSIX thread functions pthread cond signal() v.s. pthread cond broadcast() for back-
ground information.
8
The implementation uses MsgWaitForMultipleObjects() on MS-Windows and pthread cond timedwait() on other sys-
tems.
<thread 2>
thread_send_message(Thread_1, b(gnu)),
thread_send_message(Thread_1, a(gnat)),
alias(+Alias)
Create a message queue that is identified by the atom Alias. Message queues created this
way must be explicitly destroyed by the user. If the alias option is omitted, an Anonymous
queue is created that is indentified by a blob (see section 11.4.7) and subject to garbage
collection.9
max size(+Size)
Maximum number of terms in the queue. If this number is reached,
thread send message/2 will suspend until the queue is drained. The option
can be used if the source, sending messages to the queue, is faster than the drain,
consuming the messages.
deadline(+AbsTime)
The call fails (silently) if no message has arrived before AbsTime. See get time/1
for the representation of absolute time. If AbsTime is earlier then the current time,
thread get message/3 fails immediately. Both resolution and maximum wait time
is platform-dependent.10
timeout(+Time)
Time is a float or integer and specifies the maximum time to wait in seconds. This is a
relative-time version of the deadline option. If both options are provided, the earlier
time is effective.
If Time is 0 or 0.0, thread get message/3 examines the queue but does not sus-
pend if no matching term is available. Note that unlike thread peek message/2, a
matching term is removed from the queue.
If Time < 0, thread get message/3 fails immediately without removing any mes-
sage from the queue.
alias(Alias)
Queue has the given alias name.
max size(Size)
Maximum number of terms that can be in the queue. See message queue create/2.
This property is not present if there is no limit (default).
size(Size)
Queue currently contains Size terms. Note that due to concurrent access the returned
value may be outdated before it is returned. It can be used for debugging purposes as well
as work distribution purposes.
The size(Size) property is always present and may be used to enumerate the created message
queues. Note that this predicate does not enumerate threads, but can be used to query the
properties of the default queue of a thread.
Explicit message queues are designed with the 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.
%% create_workers(?Id, +N)
%
10
The implementation uses MsgWaitForMultipleObjects() on MS-Windows and pthread cond timedwait() on other sys-
tems.
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.
%% post_job(+Id, +Goal)
%
% Post a job to be executed by one of the pools workers.
post_job(Id, Goal) :-
thread_send_message(Id, Goal).
:- thread_local
foo/1.
foo(gnat).
DISCLAIMER Whether or not this declaration is appropriate in the sense of the proper mech-
anism to reach the goal is still debated. If you have strong feelings in favour or against, please
share them in the SWI-Prolog mailing list.
The code below provides a solution to this problem based on with mutex/2. It also il-
lustrates the problem of mutexes. The predicate with mutex/2 behaves as once/1 with re-
spect to the guarded goal. This means that our predicate address/2 is no longer a nice logical
non-deterministic relation. This could be solved by explicit locking and unlocking a mutex using
setup call cleanup/2, but at the risk of deadlocking the program if the choice point is left
open by accident.
change_address(Id, Address) :-
with_mutex(addressbook,
( retractall(address(Id, _)),
asserta(address_db(Id, Address))
)).
address(Id, Address) :-
with_mutex(addressbook,
address_db(Id, Address)).
Message queues (see message queue create/3) often provide simpler and more robust ways
for threads to communicate. Still, mutexes can be a sensible solution and are therefore provided.
mutex create(?MutexId)
Create a mutex. If MutexId is an atom, a named mutex is created. If it is a variable, an anony-
mous mutex reference is returned. Anonymous mutexes are subject to (atom) garbage
collection.
alias(Alias)
Set the alias name. Using mutex create(X, [alias(name)]) is preferred over the equiv-
alent mutex create(name).
mutex destroy(+MutexId)
Destroy a mutex. If the mutex is not locked, it is destroyed and further access yields an
existence error exception. As of version 7.1.19, this behaviour is reliable. If the mutex
is locked, the mutex is sheduled for delayed destruction: it will be destroyed when it becomes
unlocked.
mutex lock(+MutexId)
Lock the mutex. Prolog mutexes are recursive mutexes: they can be locked multiple times by
the same thread. Only after unlocking it as many times as it is locked does the mutex become
available for locking by other threads. If another thread has locked the mutex the calling thread
is suspended until the mutex is unlocked.
If MutexId is an atom, and there is no current mutex with that name, the mutex is created
automatically using 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 with mutex/2, which provides a safer way for handling Prolog-level mutexes. The
predicate setup call cleanup/3 is another way to guarantee that the mutex is unlocked
while retaining non-determinism.
mutex trylock(+MutexId)
As mutex lock/1, but if the mutex is held by another thread, this predicates fails immedi-
ately.
mutex unlock(+MutexId)
Unlock the mutex. This can only be called if the mutex is held by the calling thread. If this is
not the case, a permission error exception is raised.
alias(Alias)
Mutex has the defined alias name. See mutex create/2 using the alias option.
status(Status)
Current status of the mutex. One of unlocked if the mutex is currently not locked,
or locked(Owner, Count) if mutex is locked Count times by thread Owner. Note that
unless Owner is the calling thread, the locked status can change at any time. There is no
useful application of this property, except for diagnostic purposes.12
threads
Lists all current threads and their status.
join threads
Join all terminated threads. For normal applications, dealing with terminated threads must be
11
The also deprecated thread exit/1 bypasses the automatic cleanup.
12
BUG: As Owner and Count are fetched separately from the mutex, the values may be inconsistent.
part of the application logic, either detaching the thread before termination or making sure it
will be joined. The predicate join threads/0 is intended for interactive sessions to reclaim
resources from threads that died unexpectedly during development.
interactor
Create a new console and run the Prolog top level in this new console. See also
attach console/0. In the Windows version a new interactor can also be created
from the Run/New thread menu.
attach console
If the current thread has no console attached yet, attach one and redirect the user streams (input,
output, and error) to the new console window. On Unix systems the console is an xterm
application. On Windows systems this requires the GUI version swipl-win.exe rather than
the console-based swipl.exe.
This predicate has a couple of useful applications. One is to separate (debugging) I/O of differ-
ent threads. Another is to start debugging a thread that is running in the background. If thread
10 is running, the following sequence starts the tracer on this thread:
tdebug(+ThreadId)
Prepare ThreadId for debugging using the graphical tracer. This implies installing the tracer
hooks in the thread and switching the thread to debug mode using debug/0. The call is
injected into the thread using thread signal/2. We refer to the documentation of this
predicate for asynchronous interaction with threads. New threads created inherit their debug
mode from the thread that created them.
tdebug
Call tdebug/1 in all running threads.
tnodebug(+ThreadId)
Disable debugging thread ThreadId.
tnodebug
Disable debugging in all threads.
tspy(:Spec, +ThreadId)
Set a spy point as spy/1 and enable the thread for debugging using tdebug/1. Note that a
spy point is a global flag on a predicate that is visible from all threads. Spy points are honoured
in all threads that are in debug mode and ignored in threads that are in nodebug mode.
tspy(:Spec)
Set a spy point as spy/1 and enable debugging in all threads using tdebug/0. Note that
removing spy points can be done using nospy/1. Disabling spy points in a specific thread is
achieved by tnodebug/1.
tprofile(+ThreadId)
Start collecting profile data in ThreadId and ask the user to hit hreturni to stop the profiler. See
section 4.41 for details on the execution profiler.
the reference count of the engine is incremented. The attr argument can be NULL to create a
thread with default attributes. Otherwise it is a pointer to a structure with the definition below.
For any field with value 0, the default is used. The cancel field may be filled with a pointer
to a function that is called when PL cleanup() terminates the running Prolog engines. If
this function is not present or returns FALSE pthread cancel() is used. The flags field defines
the following flags:
PL THREAD NO DEBUG
If this flag is present, the thread starts in normal no-debug status. By default, the debug
status is inherited from the main thread.
typedef struct
{ unsigned long local_size; /* Stack sizes (Kbytes) */
unsigned long global_size;
unsigned long trail_size;
unsigned long argument_size;
char * alias; /* alias name */
int (*cancel)(int thread);
intptr_t flags;
} PL_thread_attr_t;
The structure may be destroyed after PL thread attach engine() has returned. On suc-
cess it returns the Prolog identifier for the thread (as returned by PL thread self()). If an
error occurs, -1 is returned. If this Prolog is not compiled for multithreading, -2 is returned.
int PL thread destroy engine()
Destroy the Prolog engine in the calling thread. Only takes ef-
fect if PL thread destroy engine() is called as many times as
PL thread attach engine() in this thread. Returns TRUE on success and FALSE
if the calling thread has no engine or this Prolog does not support threads.
Please note that construction and destruction of engines are relatively expensive operations.
Only destroy an engine if performance is not critical and memory is a critical resource.
int PL thread at exit(void (*function)(void *), void *closure, int global)
Register a handle to be called as the Prolog engine is destroyed. The handler function is called
with one void * argument holding closure. If global is TRUE, the handler is installed for all
threads. Globally installed handlers are executed after the thread-local handlers. If the handler
is installed local for the current thread only (global == FALSE) it is stored in the same FIFO
queue as used by thread at exit/1.
Traditionally, XPCE runs in the foreground (main) thread. We are working towards a situation
where XPCE can run comfortably in a separate thread. A separate XPCE thread can be created using
pce dispatch/1. It is also possible to create this thread as the (pce) is loaded by setting the
xpce threaded to true.
Threads other than the thread in which XPCE runs are provided with two predicates to communi-
cate with XPCE.
pce dispatch(+Options)
Create a Prolog thread with the alias name pce for XPCE event handling. In the X11 version
this call creates a thread that executes the X11 event-dispatch loop. In MS-Windows it creates
a thread that executes a windows event-dispatch loop. The XPCE event-handling thread has
the alias pce. Options specifies the thread attributes as thread create/3.
2. Access the terms produced in forward execution through backtracking without collecting all of
them first. Section 10.1.1 illustrates this as well.
get_answers(E, [H|T]) :-
engine_next(E, H), !,
get_answers(E, T).
get_answers(_, []).
The above is not a particularly attractive alternative for the built-in findall/3. It is mostly slower
due to time required to create and destroy the engine as well as the (currently1 ) higher overhead of
copying terms between engines than the overhead required by the dedicated representation used by
findall/3.
It gets more interesting if we wish to combine answers from multiple backtracking predicates.
Assume we have two predicates that, on backtracking, return ordered solutions and we wish to merge
the two answer streams into a single ordered stream of answers. The solution in classical Prolog is
below. It collects both answer sets, merges them using ordered set merging and extract the answers.
The code is clean and short, but it doesnt produce any answers before both generaters are fully
enumerated and it uses memory that is proportional to the combined set of answers.
merge_answers(T1,G1, T2,G2, A) :-
findall(T1, G1, L1),
findall(T2, G2, L2),
ord_union(L1, L2, Ordered),
member(A, Ordered).
We can achieve the same using engines. We create two engines to generate the solutions to both our
generators. Now, we cas ask both for an answer, put the smallest in the answer set and ask the engine
that created the smallest for its next answer, etc. This way we can create an ordered list of answers
as above, but now without creating intermediate lists. We can avoid creating the intermediate list by
introducing a third engine that controls the two generators and yields the answers rather than putting
them in a list. This is a general example of turning a predicate that builds a set of terms into a non-
deterministic predicate that produces the results on backtracking. The full code is below. Merging the
answers of two generators, each generating a set of 10,000 integers is currently about 20% slower than
the code above, but the engine-based solution runs in constant space and generates the first solution
immediately after both our generators have produced their first solution.
1
The current implementation of engines is built on top of primitives that are not optimal for the engine use case. There
is considerable opportunity to reduce the overhead.
merge(T1,G1, T2,G2, A) :-
engine_create(A, merge(T1,G1, T2,G2), E),
repeat,
( engine_next(E, A)
-> true
; !, fail
).
merge(T1,G1, T2,G2) :-
engine_create(T1, G1, E1),
engine_create(T2, G2, E2),
( engine_next(E1, S1)
-> ( engine_next(E2, S2)
-> order_solutions(S1, S2, E1, E2)
; yield_remaining(S1, E1)
)
; engine_next(E2, S2),
yield_remaining(S2, E2)
).
yield_remaining(S, E) :-
engine_yield(S),
engine_next(E, S1),
yield_remaining(S1, E).
backtracking is required, using an additional argument or backtrackable global variable is the right ap-
proach. Otherwise, non-backtrackable global variables (nb setval/2) and dynamic database come
into the picture, where global variables are always local to a thread and the dynamic database may or
may not be shared between threads (see thread local/1).
Engines bring an alternative that packages a state inside the engine where it is typically represented
in a (threaded) Prolog variable. The state may be updated, while controlled backtracking to a previous
state belongs to the possibilities. It can be accessed and updated by anyone with access to the engines
handle. Using an engine to represent state has the following advantages:
The programming style needed inside the engine is much more Prolog friendly, using
engine fetch/1 to read a request and engine yield/1 to reply to it.
The state may be accessed from multiple threads. Access to the state is synchronized without
the need for explicit locks.
The example below implements a shared priority heap based on library heaps. The predicate
update heap/1 shows the typical update loop for maintaining state inside an engine: fetch a com-
mand, update the state, yield with the reply and call the updater recursively. The update step is guarded
against failure. For robustness one may also guard it against exceptions using catch/3. Note that
heap get/2 passes the Priority and Key it wishes to delete from the heap such that if the unification
fails, the heap remains unchanged.
The resulting heap is a global object with either a named or anonymous handle that evolves inde-
pendently from the Prolog thread(s) that access it. If the heap is anonymous, it is subject to (atom)
garbage collection.
:- use_module(library(heaps)).
create_heap(E) :-
empty_heap(H),
engine_create(_, update_heap(H), E).
update_heap(H) :-
engine_fetch(Command),
( update_heap(Command, Reply, H, H1)
-> true
; H1 = H,
Reply = false
),
engine_yield(Reply),
update_heap(H1).
heap_add(Priority, Key, E) :-
engine_post(E, add(Priority, Key), true).
heap_get(Priority, Key, E) :-
engine_post(E, get(Priority, Key), Priority-Key).
This section needs an example. Preferably something that fits on one page and would
not scale using threads. Engines might work nice to implement Antrank: An ant colony
algorithm for ranking web pages.2
alias(+Name)
Give the engine a name. Name must be an atom. If this option is provided, Engine is
unified with Name. The name space for engines is shared with threads and mutexes.
global(KBytes)
Set the limit for the global stack in KBytes.
local(KBytes)
Set the limit for the local stack in KBytes.
trail(KBytes)
Set the limit for the trail stack in KBytes.
the(Answer)
Goal succeeded with Template bound to Answer or Goal yielded with a term Answer.
no
Goal failed.
exception(Exception)
Goal raises the error Exception.
can only be called if the engine is not involved in a callback from C, i.e., when the engine calls
a predicate defined in C that calls back Prolog it is not possible to use this predicate. Trying to
do so results in a permission error exception.
is engine(@Term) [semidet]
True if Term is a reference to or the alias name of an existing engine.
are linked to a shared library (.so file on most Unix systems) or dynamic link library (.DLL file on
Microsoft platforms) and loaded into the running Prolog process.1
11.2.3 library(shlib): Utility library for loading foreign objects (DLLs, shared objects)
This section discusses the functionality of the (autoload) library(shlib), providing an interface
to manage shared libraries. We describe the procedure for using a foreign resource (DLL in Windows
and shared object in Unix) called mylib.
First, one must assemble the resource and make it compatible to SWI-Prolog. The details for this
vary between platforms. The swipl-ld(1) utility can be used to deal with this in a portable manner.
The typical commandline is:
Make sure that one of the files provides a global function install_mylib() that initialises
the module using calls to PL register foreign(). Here is a simple example file mylib.c, which creates
a Windows MessageBox:
#include <windows.h>
#include <SWI-Prolog.h>
static foreign_t
pl_say_hello(term_t to)
{ char *a;
1
The system also contains code to load .o files directly for some operating systems, notably Unix systems using the
BSD a.out executable format. As the number of Unix platforms supporting this quickly gets smaller and this interface is
difficult to port and slow, it is no longer described in this manual. The best alternative would be to use the dld package on
machines that do not have shared libraries.
if ( PL_get_atom_chars(to, &a) )
{ MessageBox(NULL, a, "DLL test", MB_OK|MB_TASKMODAL);
PL_succeed;
}
PL_fail;
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
The file mylib.pl can be loaded as a normal Prolog file and provides the predicate defined in
C.
...
load_foreign_library(foreign(mylib)),
...
Arguments
FileSpec is a specification for absolute file name/3. If search-
ing the file fails, the plain name is passed to the OS to try
the default method of the OS for locating foreign objects. The
default definition of file search path/2 searches <prolog
home>/lib/<arch> on Unix and <prolog home>/bin on Win-
dows.
See also use foreign library/1,2 are intended for use in directives.
:- initialization(load_foreign_library(foreign(mylib))).
but using the initialization/1 wrapper causes the library to be loaded after loading of
the file in which it appears is completed, while use foreign library/1 loads the library
immediately. I.e. the difference is only relevant if the remainder of the file uses functionality of
the C-library.
unload foreign library(+FileSpec) [det]
unload foreign library(+FileSpec, +Exit:atom) [det]
Unload a shared object or DLL. After calling the Exit function, the shared object is removed
from the process. The default exit function is composed from =uninstall =, followed by the file
base-name.
current foreign library(?File, ?Public)
Query currently loaded shared libraries.
reload foreign libraries
Reload all foreign libraries loaded (after restore of a state created using qsave program/2.
.../swipl/runtime/harchi/libswipl.a SWI-Library
.../swipl/include/SWI-Prolog.h Include file
.../swipl/include/SWI-Stream.h Stream I/O include file
.../swipl/include/SWI-Exports Export declarations (AIX only)
.../swipl/include/stub.c Extension stub
The definition of the foreign predicates is the same as for dynamic linking. Unlike with dynamic
linking, however, there is no initialisation function. Instead, the file .../swipl/include/stub.
c may be copied to your project and modified to define the foreign extensions. Below is stub.c,
modified to link the lowercase example described later in this chapter:
#include <stdio.h>
#include <SWI-Prolog.h>
PL_extension predicates[] =
{
/*{ "name", arity, function, PL_FA_<flags> },*/
{ "lowercase", 2 pl_lowercase, 0 },
{ NULL, 0, NULL, 0 } /* terminating line */
};
int
main(int argc, char **argv)
{ PL_register_extensions(predicates);
if ( !PL_initialise(argc, argv) )
PL_halt(1);
PL_halt(PL_toplevel() ? 0 : 1);
}
Now, a new executable may be created by compiling this file and linking it to libpl.a from the
runtime directory and the libraries required by both the extensions and the SWI-Prolog kernel. This
may be done by hand, or by using the swipl-ld utility described in section 11.5. If the linking is
performed by hand, the command line option -dump-runtime-variables (see section 2.4) can
be used to obtain the required paths, libraries and linking options to link the new executable.
WARNING Term references that are accessed in write (-) mode will refer to an invalid term if
the term is allocated on the global stack and backtracking takes us back to a point before the term was
written.2 Compounds, large integers, floats and strings are all allocated on the global stack. Below is
a typical scenario where this may happen. The first solution writes a term extracted from the solution
into a. After the system backtracks due to PL next solution(), a becomes a reference to a term
that no longer exists.
term_t a = PL_new_term_ref();
...
query = PL_open_query(...);
while(PL_next_solution(query))
{ PL_get_arg(i, ..., a);
}
PL_close_query(query);
2
This could have been avoided by trailing term references when data is written to them. This seriously hurds performance
in some scenarios though. If this is desired, use PL put variable() followed by one of the PL unify *() functions.
There are two solutions to this problem. One is to scope the term reference using
PL open foreign frame() and PL close foreign frame() and makes sure it goes
out of scope before backtracking happens. The other is to clear the term reference using
PL put variable() before backtracking.
Term references are obtained in any of the following ways:
Passed as argument
The C functions implementing foreign predicates are passed their arguments as term references.
These references may be read or unified. Writing to these variables causes undefined behaviour.
Term references can safely be copied to other C variables of type term t, but all copies will
always refer to the same term.
...
}
functor t A functor is the internal representation of a name/arity pair. They are used to find the name
and arity of a compound term as well as to construct new compound terms. Like atoms they
live for the whole Prolog session and are unique.
predicate t Handle to a Prolog predicate. Predicate handles live forever (although they can lose their
definition).
module t A module is a unique handle to a Prolog module. Modules are used only to call predicates
in a specific module.
control t Passed as additional argument to non-deterministic foreign functions. See PL retry*() and
PL foreign context*().
install t Type for the install() and uninstall() functions of shared or dynamic link libraries. See sec-
tion 11.2.3.
int64 t Actually part of the C99 standard rather than Prolog. As of version 5.5.6, Prolog integers are
64-bit on all hardware. The C99 type int64 t is defined in the stdint.h standard header
and provides platform-independent 64-bit integers. Portable code accessing Prolog should use
this type to exchange integer values. Please note that PL get long() can return FALSE on
Prolog integers that cannot be represented as a C long. Robust code should not assume any of
the integer fetching functions to succeed, even if the Prolog term is known to be an integer.
PL ARITY AS SIZE
As of SWI-Prolog 7.3.12, the arity of terms has changed from int to size t. To deal with this tran-
sition, all affecting functions have two versions, where the old name exchanges the arity as int and a
new function with name * sz() exchanges the arity as size t. If the C macro PL ARITY AS SIZE
is defined before loading SWI-Prolog.h, macros are put in place that map the old names to the
new functions. Without precautions, the old code is compatible, but the following warning is printed
when compiling:
To make the code compile silently again, include SWI-Prolog.h as below and change the types
you use to represent arity from int to size t. Please be aware that size t is unsigned.
#define PL_ARITY_AS_SIZE
#include <SWI-Prolog.h>
be prepared to be simultaneously active in more than one goal. Suppose the natural number below n/2
is a non-deterministic foreign predicate, backtracking over all natural numbers lower than the first ar-
gument. Now consider the following predicate:
quotient_below_n(Q, N) :-
natural_number_below_n(N, N1),
natural_number_below_n(N, N2),
Q =:= N1 / N2, !.
In this predicate the function natural number below n/2 simultaneously generates solutions for both
its invocations.
Non-deterministic foreign functions should be prepared to handle three different calls from Prolog:
Both the context information and the type of call is provided by an argument of type
control t appended to the argument list for deterministic foreign functions. The macro
PL foreign control() extracts the type of call from the control argument. The foreign func-
tion can pass a context handle using the PL retry*() macros and extract the handle from the extra
argument using the PL foreign context*() macro.
foreign_t
my_function(term_t a0, term_t a1, control_t handle)
{ struct context * ctxt;
switch( PL_foreign_control(handle) )
{ case PL_FIRST_CALL:
ctxt = malloc(sizeof(struct context));
...
PL_retry_address(ctxt);
case PL_REDO:
ctxt = PL_foreign_context_address(handle);
...
PL_retry_address(ctxt);
case PL_PRUNED:
ctxt = PL_foreign_context_address(handle);
...
free(ctxt);
PL_succeed;
}
}
Please note that the following two calls are different with respect to atom garbage collection:
PL_unify_atom_chars(t, "text");
PL_unify_atom(t, PL_new_atom("text"));
The latter increments the reference count of the atom text, which effectively ensures the atom will
never be collected. It is advised to use the * chars() or * nchars() functions whenever applicable.
if ( PL_is_atom(t) )
{ char *s;
PL_get_atom_chars(t, &s);
...;
}
or
char *s;
if ( PL_get_atom_chars(t, &s) )
{ ...;
}
Version 7 added PL NIL, PL BLOB, PL LIST PAIR and PL DICT. Older versions classify
PL NIL and PL BLOB as PL ATOM, PL LIST PAIR as PL TERM and do not have dicts.
int PL is variable(term t)
Returns non-zero if term is a variable.
int PL is ground(term t)
Returns non-zero if term is a ground term. See also ground/1. This function is cycle-safe.
int PL is atom(term t)
Returns non-zero if term is an atom.
int PL is string(term t)
Returns non-zero if term is a string.
int PL is integer(term t)
Returns non-zero if term is an integer.
int PL is float(term t)
Returns non-zero if term is a float.
int PL is callable(term t)
Returns non-zero if term is a callable term. See callable/1 for details.
int PL is compound(term t)
Returns non-zero if term is a compound term.
int PL is functor(term t, functor t)
Returns non-zero if term is compound and its functor is functor. This test is equivalent to
PL get functor(), followed by testing the functor, but easier to write and faster.
int PL is list(term t)
Returns non-zero if term is a compound term using the list constructor or the list terminator.
See also PL is pair() and PL skip list().
int PL is pair(term t)
Returns non-zero if term is a compound term using the list constructor. See also
PL is list() and PL skip list().
int PL is atomic(term t)
Returns non-zero if term is atomic (not variable or compound).
int PL is number(term t)
Returns non-zero if term is an integer or float.
int PL is acyclic(term t)
Returns non-zero if term is acyclic (i.e. a finite tree).
CVT ATOM
Convert if term is an atom.
CVT STRING
Convert if term is a string.
CVT LIST
Convert if term is a list of of character codes.
CVT INTEGER
Convert if term is an integer.
CVT FLOAT
Convert if term is a float. The characters returned are the same as write/1 would write
for the floating point number.
CVT NUMBER
Convert if term is an integer or float.
CVT ATOMIC
Convert if term is atomic.
CVT VARIABLE
Convert variable to print-name
CVT WRITE
Convert any term that is not converted by any of the other flags using write/1. If no
BUF * is provided, BUF RING is implied.
CVT WRITE CANONICAL
As CVT WRITE, but using write canonical/2.
CVT WRITEQ
As CVT WRITE, but using writeq/2.
CVT ALL
Convert if term is any of the above, except for CVT VARIABLE and CVT WRITE*.
CVT EXCEPTION
If conversion fails due to a type error, raise a Prolog type error exception in addition to
failure
BUF DISCARDABLE
Data must copied immediately
BUF RING
Data is stored in a ring of buffers
BUF MALLOC
Data is copied to a new buffer returned by PL malloc(3). When no longer needed the
user must call PL free() on the data.
REP ISO LATIN 1
Text is in ISO Latin-1 encoding and the call fails if text cannot be represented. This flag
has the value 0 and is thus the default.
REP UTF8
Convert the text to a UTF-8 string. This works for all text.
REP MB
Convert to default locale-defined 8-bit string. Success depends on the locale. Conversion
is done using the wcrtomb() C library function.
int PL get nchars(term t t, size t *len, char **s, unsigned int flags)
See PL get chars().
In addition, the following functions are available for creating and inspecting atoms:
Wide-character versions
Support for exchange of wide-character strings is still under consideration. The functions dealing
with 8-bit character strings return failure when operating on a wide-character atom or Prolog string
object. The functions below can extract and unify both 8-bit and wide atoms and string objects. Wide
character strings are represented as C arrays of objects of the type pl wchar t, which is guaranteed
to be the same as wchar t on platforms supporting this type. For example, on MS-Windows, this
represents 16-bit UCS2 characters, while using the GNU C library (glibc) this represents 32-bit UCS4
characters.
int PL unify wchars(term t t, int type, size t len, const pl wchar t *s)
Unify t with a textual representation of the C wide-character array s. The type argument de-
fines the Prolog representation and is one of PL ATOM, PL STRING, PL CODE LIST or
PL CHAR LIST.
int PL unify wchars diff(term t +t, term t -tail, int type, size t len, const pl wchar t *s)
Difference list version of PL unify wchars(), only supporting the types PL CODE LIST
and PL CHAR LIST. It serves two purposes. It allows for returning very long lists from
data read from a stream without the need for a resizing buffer in C. Also, the use of dif-
ference lists is often practical for further processing in Prolog. Examples can be found in
packages/clib/readutil.c from the source distribution.
Reading a list
The functions from this section are intended to read a Prolog list from C. Suppose we expect a list of
atoms; the following code will print the atoms, each on a line:
foreign_t
pl_write_atoms(term_t l)
{ term_t head = PL_new_term_ref(); /* the elements */
term_t list = PL_copy_term_ref(l); /* copy (we modify list) */
if ( PL_get_atom_chars(head, &s) )
Sprintf("%s\n", s);
else
PL_fail;
}
Note that as of version 7, lists have a new representation unless the option --traditional is used.
see section 5.1.
int PL get list(term t +l, term t -h, term t -t)
If l is a list and not the empty list, assign a term reference to the head to h and to the tail to t.
int PL get head(term t +l, term t -h)
If l is a list and not the empty list, assign a term reference to the head to h.
int PL get tail(term t +l, term t -t)
If l is a list and not the empty list, assign a term reference to the tail to t.
int PL get nil(term t +l)
Succeeds if l represents the list termination constant.
int PL skip list(term t +list, term t -tail, size t *len)
This is a multi-purpose function to deal with lists. It allows for finding the length of a list,
checking whether something is a list, etc. The reference tail is set to point to the end of the list,
len is filled with the number of list-cells skipped, and the return value indicates the status of the
list:
PL LIST
The list is a proper list: one that ends in the list terminator constant and tail is filled with
the terminator constant.
PL PARTIAL LIST
The list is a partial list: one that ends in a variable and tail is a reference to this variable.
PL CYCLIC TERM
The list is cyclic (e.g. X = [aX]). tail points to an arbitrary cell of the list and len is at
most twice the cycle length of the list.
PL NOT A LIST
The term list is not a list at all. tail is bound to the non-list term and len is set to the
number of list-cells skipped.
foreign_t
pl_display(term_t t)
{ functor_t functor;
int arity, len, n;
char *s;
switch( PL_term_type(t) )
{ case PL_VARIABLE:
case PL_ATOM:
case PL_INTEGER:
case PL_FLOAT:
PL_get_chars(t, &s, CVT_ALL);
Sprintf("%s", s);
break;
case PL_STRING:
PL_get_string_chars(t, &s, &len);
Sprintf("\"%s\"", s);
break;
case PL_TERM:
{ term_t a = PL_new_term_ref();
PL_succeed;
}
{ term_t a1 = PL_new_term_ref();
term_t a2 = PL_new_term_ref();
term_t t = PL_new_term_ref();
functor_t animal2;
PL_put_atom_chars(a1, "gnu");
PL_put_integer(a2, 50);
PL_cons_functor(t, animal2, a1, a2);
}
After this sequence, the term references a1 and a2 may be used for other purposes.
void
put_list(term_t l, int n, char **words)
{ term_t a = PL_new_term_ref();
PL_put_nil(l);
while( --n >= 0 )
{ PL_put_atom_chars(a, words[n]);
PL_cons_list(l, a, l);
}
}
Note that l can be redefined within a PL cons list call as shown here because operationally
its old value is consumed before its new value is set.
foreign_t
pl_hostname(term_t name)
{ char buf[100];
if ( gethostname(buf, sizeof(buf)) )
{ term_t tmp = PL_new_term_ref();
PL_put_atom_chars(tmp, buf);
return PL_unify(name, tmp);
}
PL_fail;
}
foreign_t
pl_hostname(term_t name)
{ char buf[100];
if ( gethostname(buf, sizeof(buf)) )
return PL_unify_atom_chars(name, buf);
PL_fail;
}
Note that unification functions that perform multiple bindings may leave part of the bindings in case
of failure. See PL unify() for details.
...
if ( !PL_unify(t1, t2) )
PL_rewind_foreign_frame(fid);
...
PL_close_foreign_frame(fid);
}
In addition, PL unify() may have failed on an exception, typically a resource (stack) over-
flow. This can be tested using PL exception(), passing 0 (zero) for the query-id argument.
Foreign functions that encounter an exception must return FAIL to Prolog as soon as possible
or call PL clear exception() if they wish to ignore the exception.
int PL unify chars(term t ?t, int flags, size t len, const char *chars)
New function to deal with unification of char* with various encodings to a Prolog represen-
tation. The flags argument is a bitwise or specifying the Prolog target type and the encoding of
chars. A Prolog type is one of PL ATOM, PL STRING, PL CODE LIST or PL CHAR LIST. A
representation is one of REP ISO LATIN 1, REP UTF8 or REP MB. See PL get chars()
for a definition of the representation types. If len is -1 chars must be zero-terminated and the
length is computed from chars using strlen().
If flags includes PL DIFF LIST and type is one of PL CODE LIST or PL CHAR LIST, the
text is converted to a difference list. The tail of the difference list is t + 1.
foreign_t
pl_get_environ(term_t env)
{ term_t l = PL_copy_term_ref(env);
term_t a = PL_new_term_ref();
extern char **environ;
char **e;
PL_fail;
}
return PL_unify_nil(l);
}
PL VARIABLE none
No op. Used in arguments of PL FUNCTOR.
PL BOOL int
Unify the argument with true or false.
PL ATOM atom t
Unify the argument with an atom, as in PL unify atom().
PL CHARS const char *
Unify the argument with an atom constructed from the C char *, as in
PL unify atom chars().
PL NCHARS size t, const char *
Unify the argument with an atom constructed from length and char* as in
PL unify atom nchars().
PL UTF8 CHARS const char *
Create an atom from a UTF-8 string.
PL UTF8 STRING const char *
Create a packed string object from a UTF-8 string.
For example, to unify an argument with the term language(dutch), the following skeleton
may be used:
static void
init_constants()
{ FUNCTOR_language1 = PL_new_functor(PL_new_atom("language"),1);
}
foreign_t
pl_get_lang(term_t r)
{ return PL_unify_term(r,
PL_FUNCTOR, FUNCTOR_language1,
PL_CHARS, "dutch");
}
install_t
install()
{ PL_register_foreign("get_lang", 1, pl_get_lang, 0);
init_constants();
}
int
call_chars(const char *goal)
{ fid_t fid = PL_open_foreign_frame();
term_t g = PL_new_term_ref();
BOOL rval;
if ( PL_chars_to_term(goal, g) )
rval = PL_call(goal, NULL);
else
rval = FALSE;
PL_discard_foreign_frame(fid);
return rval;
}
...
call_chars("consult(load)");
...
static foreign_t
set_size(term_t name, term_t width, term_t height)
{ char *n;
int w, h;
...
int PL permission error(const char *operation, const char *type, term t culprit)
Raise permission error(operation, type, culprit). See
permission error/3.
For each type, exactly one such structure should be allocated. Its first field must be initialised to
PL BLOB MAGIC. The flags is a bitwise or of the following constants:
PL BLOB TEXT
If specified the blob is assumed to contain text and is considered a normal Prolog atom.
PL BLOB UNIQUE
If specified the system ensures that the blob-handle is a unique reference for a blob with the
given type, length and content. If this flag is not specified, each lookup creates a new blob.
PL BLOB NOCOPY
By default the content of the blob is copied. Using this flag the blob references the external
data directly. The user must ensure the provided pointer is valid as long as the atom lives. If
PL BLOB UNIQUE is also specified, uniqueness is determined by comparing the pointer rather
than the data pointed at.
The name field represents the type name as available to Prolog. See also current blob/2.
The other fields are function pointers that must be initialised to proper functions or NULL to get the
default behaviour of built-in atoms. Below are the defined member functions:
void acquire(atom t a)
Called if a new blob of this type is created through PL put blob() or PL unify blob().
This callback may be used together with the release hook to deal with reference-counted
external objects.
int release(atom t a)
The blob (atom) a is about to be released. This function can retrieve the data of the blob using
PL blob data(). If it returns FALSE the atom garbage collector will not reclaim the atom.
If this function is not provided, write/1 emits the content of the blob for blobs of type
PL BLOB TEXT or a string of the format <#hex data> for binary blobs.
If a blob type is registered from a loadable object (shared object or DLL) the blob type must be
deregistered before the object may be released.
Accessing blobs
The blob access functions are similar to the atom accessing functions. Blobs being atoms, the atom
functions operate on blobs and vice versa. For clarity and possible future compatibility issues, how-
ever, it is not advised to rely on this.
SWI-Prolog normally rebinds the GMP allocation functions using mp set memory functions().
This means SWI-Prolog must be initialised before the foreign code touches any GMP function.
You can call \cfuncref{PL_action}{PL_GMP_SET_ALLOC_FUNCTIONS, TRUE}
to force Prologs GMP initialization without doing the rest of the Prolog ini-
tialization. If you do not want Prolog rebinding the GMP allocation, call
\cfuncref{PL_action}{PL_GMP_SET_ALLOC_FUNCTIONS, FALSE} before
initializing Prolog.
On Windows, each DLL has its own memory pool. To make exchange of GMP numbers be-
tween Prolog and foreign code possible you must either let Prolog rebind the allocation func-
tions (default) or you must recompile SWI-Prolog to link to a DLL version of the GMP library.
#include <gmp.h>
#include <SWI-Prolog.h>
static foreign_t
next_prime(term_t n, term_t prime)
{ mpz_t mpz;
int rc;
mpz_init(mpz);
if ( PL_get_mpz(n, mpz) )
{ mpz_nextprime(mpz, mpz);
rc = PL_unify_mpz(prime, mpz);
} else
rc = FALSE;
mpz_clear(mpz);
return rc;
}
install_t
install()
{ PL_register_foreign("next_prime", 2, next_prime, 0);
}
number and the function returns TRUE. Otherwise mpq is untouched and the function returns
FALSE. Note that mpq must have been initialised before calling this function and must be
cleared using mpq clear() to reclaim any storage associated with it.
int PL unify mpz(term t t, mpz t mpz)
Unify t with the integer value represented by mpz and return TRUE on success. The mpz
argument is not changed.
int PL unify mpq(term t t, mpq t mpq)
Unify t with a rational number represented by mpq and return TRUE on success. Note that t is
unified with an integer if the denominator is 1. The mpq argument is not changed.
Predicate references
This section discusses the functions used to communicate about predicates. Though a Prolog predicate
may be defined or not, redefined, etc., a Prolog predicate has a handle that is neither destroyed nor
moved. This handle is known by the type predicate t.
PL Q NORMAL
Normal operation. The debugger inherits its settings from the environment. If an excep-
tion occurs that is not handled in Prolog, a message is printed and the tracer is started to
debug the error.5
PL Q NODEBUG
Switch off the debugger while executing the goal. This option is used by many calls
to hook-predicates to avoid tracing the hooks. An example is print/1 calling
portray/1 from foreign code.
PL Q CATCH EXCEPTION
If an exception is raised while executing the goal, do not report it, but make it available
for PL exception().
PL Q PASS EXCEPTION
As PL Q CATCH EXCEPTION, but do not invalidate the exception-term while calling
PL close query(). This option is experimental.
PL Q ALLOW YIELD
Support the I YIELD instruction for engine-based coroutining. See
$engine yield/2 in boot/init.pl for details.
PL Q EXT STATUS
Make PL next solution() return extended status. Instead of only TRUE or FALSE
extended status as illustrated in the following table:
Extended Normal
PL S EXCEPTION FALSE Exception available through PL exception()
PL S FALSE FALSE Query failed
PL S TRUE TRUE Query succeeded with choicepoint
PL S LAST TRUE Query succeeded without choicepoint
PL open query() can return the query identifier 0 if there is not enough space on the
environment stack. This function succeeds, even if the referenced predicate is not defined. In
this case, running the query using PL next solution() will return an existence error. See
PL exception().
5
Do not pass the integer 0 for normal operation, as this is interpreted as PL Q NODEBUG for backward compatibility
reasons.
The example below opens a query to the predicate is_a/2 to find the ancestor of me. The
reference to the predicate is valid for the duration of the process and may be cached by the
client.
char *
ancestor(const char *me)
{ term_t a0 = PL_new_term_refs(2);
static predicate_t p;
if ( !p )
p = PL_predicate("is_a", 2, "database");
PL_put_atom_chars(a0, me);
PL_open_query(NULL, PL_Q_NORMAL, p, a0);
...
}
int
count_atoms()
{ fid_t fid = PL_open_foreign_frame();
term_t goal = PL_new_term_ref();
term_t a1 = PL_new_term_ref();
term_t a2 = PL_new_term_ref();
functor_t s2 = PL_new_functor(PL_new_atom("statistics"), 2);
int atoms;
PL_put_atom_chars(a1, "atoms");
PL_cons_functor(goal, s2, a1, a2);
PL_call(goal, NULL); /* call it in current module */
PL_get_integer(a2, &atoms);
PL_discard_foreign_frame(fid);
return atoms;
}
while leaving the term references. The calls below may be used to destroy term references and data.
See figure 11.3 for an example.
It is obligatory to call either of the two closing functions to discard a foreign frame. Foreign
frames may be nested.
module t PL context()
Return the module identifier of the context module of the currently active foreign predicate.
{ module m = PL_new_module(PL_new_atom("user"));
term_t plain = PL_new_term_ref();
If PL next solution() succeeds, the result is analysed and translated to a number, after
which the query is closed and all Prolog data created after PL open foreign frame() is de-
stroyed. On the other hand, if PL next solution() fails and if an exception was raised, just
pass it. Otherwise generate an exception (PL error() is an internal call for building the standard
error terms and calling PL raise exception()). After this, the Prolog environment should be
discarded using PL cut query() and PL close foreign frame() to avoid invalidating the
exception term.
static int
prologFunction(ArithFunction f, term_t av, Number r)
{ int arity = f->proc->definition->functor->arity;
fid_t fid = PL_open_foreign_frame();
qid_t qid;
int rval;
if ( PL_next_solution(qid) )
{ rval = valueExpression(av+arity-1, r);
PL_close_query(qid);
PL_discard_foreign_frame(fid);
} else
{ term_t except;
if ( (except = PL_exception(qid)) )
{ rval = PL_throw(except); /* pass exception */
} else
{ char *name = stringAtom(f->proc->definition->functor->name);
/* generate exception */
rval = PL_error(name, arity-1, NULL, ERR_FAILED, f->proc);
}
return rval;
}
foreign_t
pl_hello(term_t to)
{ char *s;
if ( PL_get_atom_chars(to, &s) )
{ Sprintf("Hello \"%s\"\n", s);
PL_succeed;
} else
{ term_t except = PL_new_term_ref();
PL_unify_term(except,
PL_FUNCTOR_CHARS, "type_error", 2,
PL_CHARS, "atom",
PL_TERM, to);
return PL_raise_exception(except);
}
}
11.4.14 Miscellaneous
Term Comparison
int PL compare(term t t1, term t t2)
Compares two terms using the standard order of terms and returns -1, 0 or 1. See also
compare/3.
Recorded database
In some applications it is useful to store and retrieve Prolog terms from C code. For example, the
XPCE graphical environment does this for storing arbitrary Prolog data as slot-data of XPCE objects.
Please note that the returned handles have no meaning at the Prolog level and the recorded terms
are not visible from Prolog. The functions PL recorded() and PL erase() are the only func-
tions that can operate on the stored term.
Two groups of functions are provided. The first group (PL record() and friends) store Prolog
terms on the Prolog heap for retrieval during the same session. These functions are also used by
recorda/3 and friends. The recorded database may be used to communicate Prolog terms between
threads.
The second group (headed by PL record external()) provides the same functionality, but
the returned data has properties that enable storing the data on an external device. It has been designed
to make it possible to store Prolog terms fast and compact in an external database. Here are the main
features:
Independent of session
Records can be communicated to another Prolog session and made visible using
PL recorded external().
Binary
The representation is binary for maximum performance. The returned data may contain zero
bytes.
Byte-order independent
The representation can be transferred between machines with different byte order.
No alignment restrictions
There are no memory alignment restrictions and copies of the record can thus be moved freely.
For example, it is possible to use this representation to exchange terms using shared memory
between different Prolog processes.
Compact
It is assumed that a smaller memory footprint will eventually outperform slightly faster repre-
sentations.
Stable
The format is designed for future enhancements without breaking compatibility with older
records.
PL FILE ABSOLUTE
Return an absolute path to the requested file.
PL FILE OSPATH
Return the name using the hosting OS conventions. On MS-Windows, \ is used to sepa-
rate directories rather than the canonical /.
PL FILE SEARCH
Invoke absolute file name/3. This implies rules from file search path/2
are used.
PL FILE EXIST
Demand the path to refer to an existing entity.
PL FILE READ
Demand read-access on the result.
PL FILE WRITE
Demand write-access on the result.
PL FILE EXECUTE
Demand execute-access on the result.
PL FILE NOERRORS
Do not raise any exceptions.
Foreign code can set or create Prolog flags using PL set prolog flag(). See
set prolog flag/2 and create prolog flag/3.8
PL BOOL
Create a boolean (true or false) flag. The argument must be an int.
PL ATOM
Create a flag with an atom as value. The argument must be of type const char *.
PL INTEGER
Create a flag with an integer as value. The argument must be of type intptr t *.
PL ACTION TRACE
Start Prolog tracer (trace/0). Requires no arguments.
PL ACTION DEBUG
Switch on Prolog debug mode (debug/0). Requires no arguments.
PL ACTION BACKTRACE
Print backtrace on current output stream. The argument (an int) is the number of frames
printed.
PL ACTION HALT
Halt Prolog execution. This action should be called rather than Unix exit() to give Prolog
the opportunity to clean up. This call does not return. The argument (an int) is the exit
code. See halt/1.
PL ACTION ABORT
Generate a Prolog abort (abort/0). This call does not return. Requires no arguments.
PL ACTION BREAK
Create a standard Prolog break environment (break/0). Returns after the user types the
end-of-file character. Requires no arguments.
PL ACTION GUIAPP
Windows: Used to indicate to the kernel that the application is a GUI application if the
argument is not 0, and a console application if the argument is 0. If a fatal error occurs,
the system uses a windows messagebox to report this on a GUI application, and otherwise
simply prints the error and exits.
PL ACTION TRADITIONAL
Same effect as using --traditional. Must be called before PL initialise().
PL ACTION WRITE
Write the argument, a char * to the current output stream.
PL ACTION FLUSH
Flush the current output stream. Requires no arguments.
PL ACTION ATTACH CONSOLE
Attach a console to a thread if it does not have one. See attach console/0.
PL GMP SET ALLOC FUNCTIONS
Takes an integer argument. If TRUE, the GMP allocations are immediately bound to the
Prolog functions. If FALSE, SWI-Prolog will never rebind the GMP allocation functions.
See mp set memory functions() in the GMP documentation. The action returns FALSE
if there is no GMP support or GMP is already initialised.
information required. int describes what information is wanted.9 The options are given in
table 11.1.
meta-argument is provided (0-9:). Note that meta-arguments are not always passed as
hmodulei:htermi. Always use PL strip module() to extract the module and plain term
from a meta-argument.10
Predicates may be registered either before or after PL initialise(). When registered be-
fore initialisation the registration is recorded and executed after installing the system predicates
and before loading the saved state.
Default calling (i.e. without PL FA VARARGS) function is passed the same number of term t
arguments as the arity of the predicate and, if the predicate is non-deterministic, an extra ar-
gument of type control t (see section 11.4.1). If PL FA VARARGS is provided, function
is called with three arguments. The first argument is a term t handle to the first argument.
Further arguments can be reached by adding the offset (see also PL new term refs()). The
second argument is the arity, which defines the number of valid term references in the argument
vector. The last argument is used for non-deterministic calls. It is currently undocumented and
should be defined of type void*. Here is an example:
static foreign_t
atom_checksum(term_t a0, int arity, void* context)
{ char *s;
if ( PL_get_atom_chars(a0, &s) )
{ int sum;
return FALSE;
}
install_t
install()
{ PL_register_foreign("atom_checksum", 2,
atom_checksum, PL_FA_VARARGS);
}
int PL register foreign(const char *name, int arity, foreign t (*function)(), int flags, ...)
Same as PL register foreign in module(), passing NULL for the module.
For details, see PL register foreign in module(). Here is an example of its usage:
if ( !PL_initialise(argc, argv) )
PL_halt(1);
...
}
#include <SWI-Stream.h>
#include <SWI-Prolog.h>
static int
atom_hook(atom_t a)
{ Sdprintf("AGC: deleting %s\n", PL_atom_chars(a));
return TRUE;
}
install_t
install()
{ old = PL_agc_hook(atom_hook);
}
install_t
11
BUG: Although both PL on halt() and at halt/1 are called in FIFO order, all at halt/1 handlers are called
before all PL on halt() handlers.
uninstall()
{ PL_agc_hook(old);
}
1. The object must be destroyed on backtracking and normal Prolog garbage collection (i.e.,
it acts as a normal Prolog term). In this case, representing the object as a Prolog string
(second option above) is the only feasible solution.
2. The data must survive Prolog backtracking. This leaves two options. One is to represent
the object using a pointer and use explicit creation and destruction, making the program-
mer responsible. The alternative is to use the blob-interface, leaving destruction to the
(atom) garbage collector.
3. The data lives as during the lifetime of a foreign function that implements a predicate. If
the predicate is deterministic, foreign automatic variables are suitable. If the predicate is
non-deterministic, the data may be allocated using malloc() and a pointer may be passed.
See section 11.4.1.
Integer sets with not-too-far-apart upper- and lower-bounds can be represented using bit-vectors.
Common set operations, such as union, intersection, etc., are reduced to simple anding and oring
the bit-vectors. This can be done using Prologs unbounded integers.
For really demanding applications, foreign representation will perform better, especially time-
wise. Bit-vectors are naturally expressed using string objects. If the string is wrapped in
bitvector/1, the lower-bound of the vector is 0 and the upper-bound is not defined; an imple-
mentation for getting and putting the sets as well as the union predicate for it is below.
#include <SWI-Prolog.h>
static int
get_bitvector(term_t in, int *len, unsigned char **data)
{ if ( PL_is_functor(in, FUNCTOR_bitvector1) )
{ term_t a = PL_new_term_ref();
PL_fail;
}
static int
PL_fail;
}
static foreign_t
pl_bitvector_union(term_t t1, term_t t2, term_t u)
{ unsigned char *s1, *s2;
int l1, l2;
if ( s3 )
{ int n;
int ml = min(l1, l2);
PL_fail;
}
install_t
install()
{ PL_register_foreign("bitvector_union", 3, pl_bitvector_union, 0);
The DDE interface (see section 4.43) represents another common usage of the foreign interface:
providing communication to new operating system features. The DDE interface requires knowledge
about active DDE server and client channels. These channels contains various foreign data types. Such
an interface is normally achieved using an open/close protocol that creates and destroys a handle. The
handle is a reference to a foreign data structure containing the relevant information.
There are a couple of possibilities for representing the handle. The choice depends on respon-
sibilities and debugging facilities. The simplest approach is to use PL unify pointer() and
PL get pointer(). This approach is fast and easy, but has the drawbacks of (untyped) point-
ers: there is no reliable way to detect the validity of the pointer, nor to verify that it is pointing to a
structure of the desired type. The pointer may be wrapped into a compound term with arity 1 (i.e.,
dde channel(hPointeri)), making the type-problem less serious.
Alternatively (used in the DDE interface), the interface code can maintain a (preferably variable
length) array of pointers and return the index in this array. This provides better protection. Especially
for debugging purposes, wrapping the handle in a compound is a good suggestion.
int
main(int argc, char **argv)
{ if ( !PL_initialise(argc, argv) )
PL_halt(1);
PL_halt(PL_toplevel() ? 0 : 1);
}
running executable. The Windows version uses this to find a module of the running executable.
If the specified module cannot be found, it tries the module libpl.dll, containing the Prolog
runtime kernel. In all these cases, the resulting file is used for two purposes:
See whether a Prolog saved state is appended to the file. If this is the case, this state will
be loaded instead of the default boot.prc file from the SWI-Prolog home directory. See
also qsave program/[1,2] and section 11.5.
Find the Prolog home directory. This process is described in detail in section 11.6.
int
main(int argc, char **argv)
{ char *av[10];
int ac = 0;
av[ac++] = argv[0];
av[ac++] = "-x";
av[ac++] = "mystate";
av[ac] = NULL;
if ( !PL_initialise(ac, av) )
PL_halt(1);
...
}
Please note that the passed argument vector may be referred from Prolog at any time and should
therefore be valid as long as the Prolog engine is used.
A good setup in Windows is to add SWI-Prologs bin directory to your PATH and either pass
a module holding a saved state, or "libpl.dll" as argv[0]. If the Prolog state is attached
to a DLL (see the -dll option of swipl-ld), pass the name of this DLL.
2. Create a C source file from the state using e.g., the Unix utility xxd(1):
% xxd -i state > state.h
3. Embed Prolog as in the example below. Instead of calling the toplevel you probably want
to call your application code.
#include <SWI-Prolog.h>
#include "state.h"
int
main(int argc, char **argv)
{ if ( !PL_set_resource_db_mem(state, state_len) ||
!PL_initialise(argc, argv) )
PL_halt(1);
return PL_toplevel();
}
Alternative to xxd, it is possible to use inline assembler, e.g. the gcc incbin instruction.
Code for gcc was provided by Roberto Bagnara on the SWI-Prolog mailinglist. Given the state
in a file state, create the following assembler program:
.globl _state
.globl _state_end
_state:
.incbin "state"
_state_end:
#include <SWI-Prolog.h>
#if __linux
#define STATE _state
13
This implies that the data must remain accessible during the lifetime of the process if open resource/3 is used.
Future versions may provide a function to detach the resource database and cause open resource/3 to raise an excep-
tion.
int
main(int argc, char **argv)
{ if ( !PL_set_resource_db_mem(STATE, STATE_END - STATE) ||
!PL_initialise(argc, argv) )
PL_halt(1);
return PL_toplevel();
}
int PL toplevel()
Runs the goal of the -t toplevel switch (default prolog/0) and returns 1 if successful,
0 otherwise.
if ( (pid=fork()) == 0 )
{ PL_cleanup_fork();
The call behaves the same on Windows, though there is probably no meaningful application.
SIGUSR2 has an empty signal handler. This signal is sent to a thread after sending a thread-signal
(see thread signal/2). It causes blocking system calls to return with EINTR, which gives
them the opportunity to react to thread-signals.
SIGINT is used by the top level to activate the tracer (typically bound to control-C). The first control-
C posts a request for starting the tracer in a safe, synchronous fashion. If control-C is hit again
before the safe route is executed, it prompts the user whether or not a forced interrupt is desired.
The --nosignals option can be used to inhibit processing of SIGINT. The handling of
SIGUSR2 is vital for dealing with blocking system call in threads. If the way SWI-Prolog uses
this signal conflicts with other applications, signal handling of either component must be modified.
The SWI-Prolog signals are defined in pl-thread.h of the source distribution.
swipl-ld will first split the options into various groups for both the C compiler and the Prolog
compiler. Next, it will add various default options to the C compiler and call it to create an executable
holding the users C code and the Prolog kernel. Then, it will call the SWI-Prolog compiler to create
a saved state from the provided Prolog files and finally, it will attach this saved state to the created
emulator to create the requested executable.
Below, it is described how the options are split and which additional options are passed.
-help
Print brief synopsis.
-pl prolog
Select the Prolog to use. This Prolog is used for two purposes: get the home directory as well
as the compiler/linker options and create a saved state of the Prolog code.
-ld linker
Linker used to link the raw executable. Default is to use the C compiler (Win32: link.exe).
-cc C compiler
Compiler for .c files found on the command line. Default is the compiler used to build SWI-
Prolog accessible through the Prolog flag c cc (Win32: cl.exe).
-c++ C++-compiler
Compiler for C++ source file (extensions .cpp, .cxx, .cc or .C) found on the command
line. Default is c++ or g++ if the C compiler is gcc (Win32: cl.exe).
-nostate
Just relink the kernel, do not add any Prolog code to the new kernel. This is used to create a new
kernel holding additional foreign predicates on machines that do not support the shared-library
(DLL) interface, or if building the state cannot be handled by the default procedure used by
swipl-ld. In the latter case the state is created separately and appended to the kernel using
cat hkerneli hstatei > houti (Win32: copy /b hkerneli+hstatei houti).
-shared
Link C, C++ or object files into a shared object (DLL) that can be loaded by the
load foreign library/1 predicate. If used with -c it sets the proper options to
compile a C or C++ file ready for linking into a shared object.
-dll
Windows only. Embed SWI-Prolog into a DLL rather than an executable.
-c
Compile C or C++ source files into object files. This turns swipl-ld into a replacement for
the C or C++ compiler, where proper options such as the location of the include directory are
passed automatically to the compiler.
-E
Invoke the C preprocessor. Used to make swipl-ld a replacement for the C or C++ compiler.
-pl-options ,. . .
Additional options passed to Prolog when creating the saved state. The first character immedi-
ately following pl-options is used as separator and translated to spaces when the argument
is built. Example: -pl-options,-F,xpce passes -F xpce as additional flags to Prolog.
-ld-options ,. . .
Passes options to the linker, similar to -pl-options.
-cc-options ,. . .
Passes options to the C/C++ compiler, similar to -pl-options.
-v
Select verbose operation, showing the various programs and their options.
-o outfile
Reserved to specify the final output file.
-llibrary
Specifies a library for the C compiler. By default, -lswipl (Win32: libpl.lib) and the libraries
needed by the Prolog kernel are given.
-Llibrary-directory
Specifies a library directory for the C compiler. By default the directory containing the Prolog
C library for the current architecture is passed.
-g | -Iinclude-directory | -Ddefinition
These options are passed to the C compiler. By default, the include directory containing
SWI-Prolog.h is passed. swipl-ld adds two additional * -Ddef flags:
-D SWI PROLOG
Indicates the code is to be connected to SWI-Prolog.
-D SWI EMBEDDED
Indicates the creation of an embedded program.
*.pl |*.qlf
Passed as input files to the Prolog compiler to create the saved state.
*
All other options. These are passed as linker options to the C compiler.
calc(Atom) :-
term_to_atom(Expr, Atom),
A is Expr,
write(A),
nl.
#include <stdio.h>
#include <SWI-Prolog.h>
int
main(int argc, char **argv)
{ char expression[MAXLINE];
char *e = expression;
char *program = argv[0];
char *plav[2];
int n;
plav[0] = program;
plav[1] = NULL;
/* initialise Prolog */
if ( !PL_initialise(1, plav) )
PL_halt(1);
PL_put_atom_chars(h0, expression);
rval = PL_call_predicate(NULL, PL_Q_NORMAL, pred, h0);
PL_halt(rval ? 0 : 1);
}
return 0;
}
SWI-Prolog 7.4 Reference Manual Figure 11.4: C source for the calc application
11.6. THE PROLOG HOME DIRECTORY 375
The C part of the application parses the command line options, initialises the Prolog engine, locates
the calc/1 predicate and calls it. The coder is in figure 11.4.
The application is now created using the following command line:
% calc pi/2
1.5708
2. If the environment variable SWI HOME DIR is defined and points to an existing directory, use
this.
3. If the environment variable SWIPL is defined and points to an existing directory, use this.
4. Locate the primary executable or (Windows only) a component (module) thereof and check
whether the parent directory of the directory holding this file contains the file swipl. If so,
this file contains the (relative) path to the home directory. If this directory exists, use this. This
is the normal mechanism used by the binary distribution.
5. If the precompiled path exists, use it. This is only useful for a source installation.
If all fails and there is no state attached to the executable or provided Windows module (see
PL initialise()), SWI-Prolog gives up. If a state is attached, the current working directory is
used.
The file search path/2 alias swi is set to point to the home directory located.
foreign_t
pl_lowercase(term_t u, term_t l)
{ char *copy;
char *s, *q;
int rval;
if ( !PL_get_atom_chars(u, &s) )
return PL_warning("lowercase/2: instantiation fault");
copy = malloc(strlen(s)+1);
return rval;
}
install_t
install()
{ PL_register_foreign("lowercase", 2, pl_lowercase, 0);
}
1 ?- load_foreign_library(lowercase).
true.
Figure 11.6: Compiling the C source and loading the object file
After recompiling the Prolog kernel all functions listed above are available to use from the debugger
(e.g. gdb) or can be placed at critical location in your code or the system code.
PL BT SAFE
(0x1) Do not try to print goals. Instead, just print the predicate name and arity. This
reduces the likelyhood to crash if PL backtrace() is called in a damaged environment.
PL BT USER
(0x2) Only show user frames. Default is to also show frames of hidden built-in predi-
cates.
The source distribution provides the script scripts/swipl-bt that exploits gdb and
PL backtrace string() to print stack traces in various formats for a SWI-Prolog pro-
cess, given its process id.
exists if the system is compiled with the cflag -DO DEBUG or -DO MAINTENANCE. This is
not the default.
The Prolog kernel sources use the macro DEBUG(Topic, Code). These macros are disabled in the
production version and must be enabled by recompiling the system as described above. Specific topics
can be enabled and disabled using the predicates prolog debug/1 and prolog nodebug/1. In
addition, they can be activated from the commandline using commandline option -d topics, where
topics is a comma-separated list of debug topics to enable. For example, the code below adds many
consistency checks and prints messages if the Prolog signal handler dispatches signals.
$ swipl -d chk_secure,msg_signal
prolog debug(+Topic)
prolog nodebug(+Topic)
Enable/disable a debug topic. Topic is an atom that identifies the desired topic. The available
topics are defined in src/pl-debug.h. Please search the sources to find out what is actually
printed and when. We highlight one topic here:
chk secure(A)
dd many expensive consistency checks to the system. This should typically be used
when the system crashes, notably in the garbage collector. Garbage collection crashes
are in most cases caused by invalid data on the Prolog stacks. This debug topic may help
locating how the invalid data was created.
Boehm-GC support
This section is obsolete. Although the Boehm-GC interfaces still exist, it turns out that
the scalability is not good enough for SWI-Prolog. It is unlikely that SWI-Prolog will
ever switch to Boehm-GC.
To accommodate future use of the Boehm garbage collector14 for heap memory allocation, the
interface provides the functions described below. Foreign extensions that wish to use the Boehm-GC
facilities can use these wrappers. Please note that if SWI-Prolog is not compiled to use Boehm-GC
(default), the user is responsible for calling PL free() to reclaim memory.
Note that shared libraries do not have this problem as the shared library loader will only look for
symbols in the main executable for symbols that are not defined in the library itself.
#define QP_put_functor(t, n, a) \
PL_put_functor(t, PL_new_functor(n, a))
The PL unify *() functions are lacking from the Quintus and SICStus interface. They can easily
be emulated, or the put/unify approach should be used to write compatible code.
The PL open foreign frame()/PL close foreign frame() combination is
lacking from both other Prologs. SICStus has PL new term refs(0), followed by
PL reset term refs(), that allows for discarding term references.
The Prolog interface for the graphical user interface package XPCE shares about 90% of the code
using a simple macro layer to deal with different naming and calling conventions of the interfaces.
local(+KBytes)
Limit for the local stack. See section 2.4.3.
global(+KBytes)
Limit for the global stack. See section 2.4.3.
trail(+KBytes)
Limit for the trail stack. See section 2.4.3.
goal(:Callable)
Initialization goal for the new executable (see -g).
toplevel(:Callable)
Top-level goal for the new executable (see -t).
init file(+Atom)
Default initialization file for the new executable. See -f.
class(+Class)
If runtime, only read resources from the state (default). If kernel, lock all predicates
as system predicates. If development, save the predicates in their current state and
keep reading resources from their source (if present). See also resource/3.
autoload(+Boolean)
If true (default), run autoload/0 first.
map(+File)
Dump a human-readable trace of what has been saved in File.
op(+Action)
One of save (default) to save the current operator table or standard to use the initial
table of the emulator.
stand alone(+Boolean)
If true, the emulator is the first part of the state. If the emulator is started it will test
whether a boot file (state) is attached to the emulator itself and load this state. Provided
the application has all libraries loaded, the resulting executable is completely independent
of the runtime environment or location where it was built. See also section 2.10.2.
emulator(+File)
File to use for the emulator. Default is the running Prolog image.
foreign(+Action)
If save, include shared objects (DLLs) into the saved state. See
current foreign library/2. If the program strip is available, this is first used
to reduce the size of the shared object. If a state is started, use foreign library/1
first tries to locate the foreign resource in the executable. When found it copies the
content of the resource to a temporary file and loads it. If possible (Unix), the temporary
object is deleted immediately after opening.1
qsave program(+File)
Equivalent to qsave program(File, []).
autoload
Check the current Prolog program for predicates that are referred to, are undefined and have a
definition in the Prolog library. Load the appropriate libraries.
This predicate is used by qsave program/[1,2] to ensure the saved state does not depend
on availability of the libraries. The predicate autoload/0 examines all clauses of the loaded
program (obtained with clause/2) and analyzes the body for referenced goals. Such an anal-
ysis cannot be complete in Prolog, which allows for the creation of arbitrary terms at runtime
and the use of them as a goal. The current analysis is limited to the following:
The analysis of meta-predicate arguments is limited to cases where the argument appears liter-
ally in the clause or is assigned using =/2 before the meta-call. That is, the following fragment
is processed correctly:
...,
Goal = prove(Theory),
forall(current_theory(Theory),
Goal)),
1
This option is experimental and currently disabled by default. It will become the default if it proves robust.
But, the calls to prove simple/1 and prove complex/1 in the example below are not
discovered by the analysis and therefore the modules that define these predicates must be loaded
explicitly using use module/1,2.
...,
member(Goal, [ prove_simple(Theory),
prove_complex(Theory)
]),
forall(current_theory(Theory),
Goal)),
It is good practice to use gxref/0 to make sure that the program has sufficient declarations
such that the analaysis tools can verify that all required predicates can be resolved and that all
code is called. See meta predicate/1, dynamic/1, public/1 and prolog:called by/2.
volatile +Name/Arity, . . .
Declare that the clauses of specified predicates should not be saved to the program. The volatile
declaration is normally used to prevent the clauses of dynamic predicates that represent data
for the current session from being saved in the state file.
If the program is an embedded Prolog application or uses the foreign language interface, care
has to be taken to restore the appropriate foreign context. See section 12.2 for details.
If the program uses directives (:- goal. lines) that perform other actions than setting predi-
cate attributes (dynamic, volatile, etc.) or loading files (consult, etc.), the directive may need to
be prefixed with initialization/1.
Database references as returned by clause/3, recorded/3, etc., are not preserved and may
thus not be part of the database when saved.
Static linking
This mechanism works on all machines, but generally requires the same C compiler and linker
to be used for the external code as is used to build SWI-Prolog itself.
To make a runtime executable that can run on multiple platforms one must make runtime checks
to find the correct way of linking. Suppose we have a source file myextension.c defining the
installation function install().
If this file is compiled into a shared library, load foreign library/1 will load this library
and call the installation function to initialise the foreign code. If it is loaded as a static extension,
define install() as the predicate install/0:
static foreign_t
pl_install()
{ install();
PL_succeed;
}
PL_extension PL_extensions [] =
{
/*{ "name", arity, function, PL_FA_<flags> },*/
{ "install", 0, pl_install, 0 },
{ NULL, 0, NULL, 0 } /* terminating line */
};
Now, use the following Prolog code to load the foreign library:
load_foreign_extensions :-
current_predicate(install, install), !, % static loaded
install.
load_foreign_extensions :- % shared library
load_foreign_library(foreign(myextension)).
:- initialization load_foreign_extensions.
The path alias foreign is defined by file search path/2. By default it searches the di-
rectories hhomei/lib/harchi and hhomei/lib. The application can specify additional rules for
file search path/2.
Before going into details, let us start with an example. Short texts can easily be expressed in Prolog
source code, but long texts are cumbersome. Assume our application defines a command help that
prints a helptext to the screen. We put the content of the helptext into a file called help.txt. The
following code implements our help command such that help.txt is incorporated into the runtime
executable.
help :-
open_resource(help, text, In),
call_cleanup(copy_stream_data(In, user_output),
close(In)).
The predicate help/0 opens the resource as a Prolog stream. If we are executing this from the devel-
opment environment, this will actually return a stream to the file help.txt itself. When executed
from the saved state, the stream will actually be a stream opened on the program resource file, taking
care of the offset and length of the resource.
l
List contents of the archive.
x
Extract named (or all) members of the archive into the current directory.
a
Add files to the archive. If the archive already contains a member with the same name, the
contents are replaced. Anywhere in the sequence of members, the options --class=class
and --encoding=encoding may appear. They affect the class and encoding of subsequent
files. The initial class is data and encoding none.
d
Delete named members from the archive.
user:file_search_path(gnatdir, swi(gnat)).
The application should locate all files using absolute file name. Suppose gnatdir contains a file
config.pl to define the local configuration. Then use the code below to load this file:
configure_gnat :-
( absolute_file_name(gnatdir(config.pl), ConfigFile)
-> consult(ConfigFile)
; format(user_error, gnat: Cannot locate config.pln),
halt(1)
).
% gnat -p gnatdir=/users/bob/lib/gnat
User definition of a built-in leads to a permission error, while using the name of a library pred-
icate is allowed.
Using libraries reduces the footprint of applications that dont need them.
The documentation of the library has just started. Material from the standard packages
should be moved here, some material from other parts of the manual should be moved
too and various libraries are not documented at all.
This library provides aggregating operators over the solutions of a predicate. The operations
are a generalisation of the bagof/3, setof/3 and findall/3 built-in predicates. The defined
aggregation operations are counting, computing the sum, minimum, maximum, a bag of solutions and
a set of solutions. We first give a simple example, computing the country with the smallest area:
smallest_country(Name, Area) :-
aggregate(min(A, N), country(N, A), min(Area, Name)).
aggregate vs. aggregate all The aggregate predicates use setof/3 (aggregate/4) or
bagof/3 (aggregate/3), dealing with existential qualified variables (VarGoal) and pro-
viding multiple solutions for the remaining free variables in Goal. The aggregate all/3
predicate uses findall/3, implicitly qualifying all free variables and providing exactly one
solution, while aggregate all/4 uses sort/2 over solutions that Discriminator (see be-
low) generated using findall/3.
The Discriminator argument The versions with 4 arguments deduplicate redundant solutions of
Goal. Solutions for which both the template variables and Discriminator are identical will be
treated as one solution. For example, if we wish to compute the total population of all countries,
and for some reason country(belgium, 11000000) may succeed twice, we can use the
following to avoid counting the population of Belgium twice:
All aggregation predicates support the following operators below in Template. In addition, they
allow for an arbitrary named compound term, where each of the arguments is a term from the list
below. For example, the term r(min(X), max(X)) computes both the minimum and maximum
binding for X.
count
Count number of solutions. Same as sum(1).
sum(Expr)
Sum of Expr for all solutions.
min(Expr)
Minimum of Expr for all solutions.
min(Expr, Witness)
A term min(Min, Witness), where Min is the minimal version of Expr over all solutions,
and Witness is any other template applied to solutions that produced Min. If multiple solutions
provide the same minimum, Witness corresponds to the first solution.
max(Expr)
Maximum of Expr for all solutions.
max(Expr, Witness)
As min(Expr, Witness), but producing the maximum result.
set(X)
An ordered set with all solutions for X.
bag(X)
A list of all solutions for X.
Acknowledgements
The development of this library was sponsored by SecuritEase, http://www.securitease.
com
?- foreach(between(1,4,X), dif(X,Y)), Y = 5.
Y = 5.
?- foreach(between(1,4,X), dif(X,Y)), Y = 3.
false.
bug Goal is copied repeatedly, which may cause problems if attributed variables are involved.
author
- Richard OKeefe
- Jan Wielemaker (made some SWI-Prolog enhancements)
This module defines meta-predicates that apply a predicate on all members of a list.
See also Older versions of SWI-Prolog had sublist/3 with the same arguments and semantics.
maplist(:Goal, ?List)
True if Goal can successfully be applied on all elements of List. Arguments are reordered to
gain performance as well as to make the predicate deterministic under normal circumstances.
A.3.1 Introduction
An association list as implemented by this library is a collection of unique keys that are associated to
values. Keys must be ground, values need not be.
An association list can be used to fetch elements via their keys and to enumerate its elements in
ascending order of their keys.
This library uses AVL trees to implement association lists. This means that
inserting a key
changing an association
fetching a single element
are all O(log(N)) worst-case (and expected) time operations, where N denotes the number of
elements in the association list.
The logarithmic overhead is often acceptable in practice. Notable advantages of association lists
over several other methods are:
the interface predicates fit the declarative nature of Prolog, avoiding destructive updates to terms
AVL trees scale very predictably and can be used to represent sparse arrays efficiently.
is assoc(+Assoc) [semidet]
True if Assoc is an association list. This predicate checks that the structure is valid, elements
are in order, and tree is balanced to the extent guaranteed by AVL trees. I.e., branches of each
subtree differ in depth by at most 1.
Changed-messages
Interface Interface
Ether
component component
Querying listen
Database broadcast
Broadcast
manipulation
assert/retract
Prolog database
...,
broadcast_request(age_of(John, Age)),
If there is an agent (listener) that registered an age-of service and knows about the age of
John this question will be answered.
listen(+Template, :Goal)
Register a listen channel. Whenever a term unifying Template is broadcasted, call Goal. The
following example traps all broadcasted messages as a variable unifies to any message. It is
commonly used to debug usage of the library.
?- listen(Term, (writeln(Term),fail)).
?- broadcast(hello(world)).
hello(world)
true.
:- pce_begin_class(name_item, text_item).
unlink(NI) :->
unlisten(NI),
send_super(NI, unlink).
:- pce_end_class.
unlisten(+Listener)
Deregister all entries created with listen/3 whose Listener unify.
unlisten(+Listener, +Template)
Deregister all entries created with listen/3 whose Listener and Template unify.
This module emulates the Quintus/SICStus library charsio.pl for reading and writing from/to
lists of character codes. Most of these predicates are straight calls into similar SWI-Prolog primitives.
Some can even be replaced by ISO standard predicates.
Compatibility The SWI-Prolog version does not require Codes to end in a full-stop.
Compatibility sicstus
This library provides some consistency checks for the loaded Prolog program. The predicate
make/0 runs list undefined/0 to find undefined predicates in user modules.
check [det]
Run all consistency checks defined by checker/2. Checks enabled by default are:
module class(+Classes)
Process modules of the given Classes. The default for classes is [user]. For example,
to include the libraries into the examination, use [user,library].
See also
- gxref/0 provides a graphical cross-referencer.
- make/0 calls list undefined/0
list redefined
Lists predicates that are defined in the global module user as well as in a normal module; that
is, predicates for which the local definition overrules the global default definition.
module class(+Classes)
Process modules of the given Classes. The default for classes is [user]. For example,
to include the libraries into the examination, use [user,library].
:- multifile check:checker/2.
check:checker(my_checks:list_format_mistakes,
"errors with format/2 arguments").
The predicate is dynamic, so you can disable checks with retract/1. For example, to stop
reporting redefined predicates:
retract(check:checker(list_redefined,_)).
A.7.1 Introduction
This library provides CLP(B), Constraint Logic Programming over Boolean variables. It can be used
to model and solve combinatorial problems such as verification, allocation and covering tasks.
CLP(B) is an instance of the general CLP(X) scheme (section 7), extending logic programming
with reasoning over specialised domains.
The implementation is based on reduced and ordered Binary Decision Diagrams (BDDs).
Usage examples of this library are available in a public git repository: github.com/triska/clpb
We recommend the following reference (PDF: metalevel.at/swiclpb.pdf) for citing this library in
scientific publications:
@inproceedings{Triska2016,
author = "Markus Triska",
title = "The {Boolean} Constraint Solver of {SWI-Prolog}:
System Description",
booktitle = "FLOPS",
series = "LNCS",
volume = 9613,
year = 2016,
pages = "45--61"
}
0 false
1 true
variable unknown truth value
atom universally quantified variable
Expr logical NOT
Expr + Expr logical OR
Expr * Expr logical AND
Expr # Expr exclusive OR
Var Expr existential quantification
Expr =:= Expr equality
Expr =\= Expr disequality (same as #)
Expr =< Expr less or equal (implication)
Expr >= Expr greater or equal
Expr < Expr less than
Expr > Expr greater than
card(Is,Exprs) see below
+(Exprs) see below
*(Exprs) see below
sat(+Expr)
True iff the Boolean expression Expr is satisfiable.
taut(+Expr, -T)
If Expr is a tautology with respect to the posted constraints, succeeds with T = 1. If Expr cannot
be satisfied, succeeds with T = 0. Otherwise, it fails.
labeling(+Vs)
Assigns truth values to the variables Vs such that all constraints are satisfied.
The unification of a CLP(B) variable X with a term T is equivalent to posting the constraint
sat(X=:=T).
A.7.4 Examples
Here is an example session with a few queries and their answers:
?- use_module(library(clpb)).
true.
?- sat(X*Y).
X = Y, Y = 1.
?- sat(X * X).
false.
?- taut(X * X, T).
T = 0,
sat(X=:=X).
?- sat(XY(X+Y)).
sat(X=:=X),
sat(Y=:=Y).
?- sat(1#X#a#b).
sat(X=:=a#b).
The pending residual goals constrain remaining variables to Boolean expressions and are declar-
atively equivalent to the original query. The last example illustrates that when applicable, remaining
variables are expressed as functions of universally quantified variables.
?- set_prolog_flag(clpb_residuals, bdd).
true.
?- sat(X#Y).
node(3)- (v(X, 0)->node(2);node(1)),
Note that this representation cannot be pasted back on the toplevel, and its details are subject to
change. Use copy term/3 to obtain such answers as Prolog terms.
The variable order of the BDD is determined by the order in which the variables first appear in
constraints. To obtain different orders, we can for example use:
?- sat(+[1,Y,X]), sat(X#Y).
node(3)- (v(Y, 0)->node(2);node(1)),
node(1)- (v(X, 1)->true;false),
node(2)- (v(X, 1)->false;true).
?- sat(X=:=1), X = 1+0.
false.
This behaviour is highly problematic from a logical point of view, and it may render declarative
debugging techniques inapplicable.
Set the flag clpb_monotonic to true to make CLP(B) monotonic. If this mode is enabled,
then you must wrap CLP(B) variables with the functor v/1. For example:
?- set_prolog_flag(clpb_monotonic, true).
true.
?- sat(v(X)=:=1#1).
X = 0.
:- use_module(library(clpb)).
:- use_module(library(clpfd)).
Example queries:
:- use_module(library(clpb)).
xor(X, Y, Z) :-
nand_gate(X, Y, T1),
nand_gate(X, T1, T2),
nand_gate(Y, T1, T3),
nand_gate(T2, T3, Z).
Using universally quantified variables, we can show that the circuit does compute XOR as intended:
?- xor(x, y, Z).
sat(Z=:=x#y).
A.7.9 Acknowledgments
The interface predicates of this library follow the example of SICStus Prolog.
Use SICStus Prolog for higher performance in many cases.
sat(+Expr) [semidet]
True iff Expr is a satisfiable Boolean expression.
labeling(+Vs) [multi]
Enumerate concrete solutions. Assigns truth values to the Boolean variables Vs such that all
stated constraints are satisfied.
?- length(Vs, 120),
sat_count(+Vs, CountOr),
sat_count(*(Vs), CountAnd).
Vs = [...],
CountOr = 1329227995784915872903807060280344575,
CountAnd = 1.
This predicate can also be used to minimize a linear Boolean program, since negative integers
can appear in Weights.
Example:
A.8.1 Introduction
This library provides CLP(FD): Constraint Logic Programming over Finite Domains. This is an
instance of the general CLP(X) scheme (section 7), extending logic programming with reasoning
over specialised domains.
CLP(FD) lets us reason about integers in a way that honors the relational nature of Prolog. An
introduction is available from metalevel.at/prolog/clpfd.
There are two major use cases of CLP(FD) constraints:
In most cases, arithmetic constraints (section A.8.2) are the only predicates you will ever need
from this library. When reasoning over integers, simply replace low-level arithmetic predicates like
(is)/2 and (>)/2 by the corresponding CLP(FD) constraints like #=/2 and #>/2 to honor and
preserve declarative properties of your programs. For satisfactory performance, arithmetic constraints
are implicitly rewritten at compilation time so that low-level fallback predicates are automatically
used whenever possible.
Almost all Prolog programs also reason about integers. Therefore, it is highly advisable that you
make CLP(FD) constraints available in all your programs. One way to do this is to put the following
directive in your /.swiplrc initialisation file:
:- use_module(library(clpfd)).
All example programs that appear in the CLP(FD) documentation assume that you have done this.
Important concepts and principles of this library are illustrated by means of usage examples that
are available in a public git repository: github.com/triska/clpfd
If you are used to the complicated operational considerations that low-level arithmetic primitives
necessitate, then moving to CLP(FD) constraints may, due to their power and convenience, at first
feel to you excessive and almost like cheating. It isnt. Constraints are an integral part of all popular
Prolog systems, and they are designed to help you eliminate and avoid the use of low-level and less
general primitives by providing declarative alternatives that are meant to be used instead.
When teaching Prolog, CLP(FD) constraints should be introduced before explaining low-level
arithmetic predicates and their procedural idiosyncrasies. This is because constraints are easy to
explain, understand and use due to their purely relational nature. In contrast, the modedness and
directionality of low-level arithmetic primitives are impure limitations that are better deferred to more
advanced lectures.
We recommend the following reference (PDF: metalevel.at/swiclpfd.pdf) for citing this library in
scientific publications:
@inproceedings{Triska12,
author = {Markus Triska},
title = {The Finite Domain Constraint Solver of {SWI-Prolog}},
booktitle = {FLOPS},
series = {LNCS},
volume = {7294},
year = {2012},
pages = {307-316}
}
More information about CLP(FD) constraints and their implementation is contained in: met-
alevel.at/drt.pdf
The best way to discuss applying, improving and extending CLP(FD) constraints is to use the ded-
icated clpfd tag on stackoverflow.com. Several of the worlds foremost CLP(FD) experts regularly
participate in these discussions and will help you for free on this platform.
in all directions. For most programs, arithmetic constraints are the only predicates you will ever need
from this library.
The most important arithmetic constraint is #=/2, which subsumes both (is)/2 and (=:=)/2
over integers. Use #=/2 to make your programs more general.
In total, the arithmetic constraints are:
:- use_module(library(clpfd)).
?- X #= 1+2.
X = 3.
This could in principle also be achieved with the lower-level predicate (is)/2. However, an
important advantage of arithmetic constraints is their purely relational nature: Constraints can be used
in all directions, also if one or more of their arguments are only partially instantiated. For example:
?- 3 #= Y+2.
Y = 1.
This relational nature makes CLP(FD) constraints easy to explain and use, and well suited for
beginners and experienced Prolog programmers alike. In contrast, when using low-level integer arith-
metic, we get:
?- 3 is Y+2.
ERROR: is/2: Arguments are not sufficiently instantiated
?- 3 =:= Y+2.
ERROR: =:=/2: Arguments are not sufficiently instantiated
Due to the necessary operational considerations, the use of these low-level arithmetic predicates
is considerably harder to understand and should therefore be deferred to more advanced lectures.
For supported expressions, CLP(FD) constraints are drop-in replacements of these low-level arith-
metic predicates, often yielding more general programs. See n_factorial/2 (section A.8.4) for
an example.
This library uses goal expansion/2 to automatically rewrite constraints at compilation time
so that low-level arithmetic predicates are automatically used whenever possible. For example, the
predicate:
positive_integer(N) :- N #>= 1.
This illustrates why the performance of CLP(FD) constraints is almost always completely sat-
isfactory when they are used in modes that can be handled by low-level arithmetic. To disable the
automatic rewriting, set the Prolog flag clpfd_goal_expansion to false.
If you are used to the complicated operational considerations that low-level arithmetic primitives
necessitate, then moving to CLP(FD) constraints may, due to their power and convenience, at first
feel to you excessive and almost like cheating. It isnt. Constraints are an integral part of all popular
Prolog systems, and they are designed to help you eliminate and avoid the use of low-level and less
general primitives by providing declarative alternatives that are meant to be used instead.
n_factorial(0, 1).
n_factorial(N, F) :-
N #> 0,
N1 #= N - 1,
n_factorial(N1, F1),
F #= N * F1.
This program uses CLP(FD) constraints instead of low-level arithmetic throughout, and every-
thing that would have worked with low-level arithmetic also works with CLP(FD) constraints, retain-
ing roughly the same performance. For example:
?- n_factorial(47, F).
F = 258623241511168180642964355153611979969197632389120000000000 ;
false.
Now the point: Due to the increased flexibility and generality of CLP(FD) constraints, we are free
to reorder the goals as follows:
n_factorial(0, 1).
n_factorial(N, F) :-
N #> 0,
N1 #= N - 1,
F #= N * F1,
n_factorial(N1, F1).
In this concrete case, termination properties of the predicate are improved. For example, the
following queries now both terminate:
?- n_factorial(N, 1).
N = 0 ;
N = 1 ;
false.
?- n_factorial(N, 3).
false.
To make the predicate terminate if any argument is instantiated, add the (implied) constraint
F #\= 0 before the recursive call. Otherwise, the query n_factorial(N, 0) is the only non-
terminating case of this kind.
The value of CLP(FD) constraints does not lie in completely freeing us from all procedural phe-
nomena. For example, the two programs do not even have the same termination properties in all cases.
Instead, the primary benefit of CLP(FD) constraints is that they allow you to try different execution
orders and apply declarative debugging techniques at all! Reordering goals (and clauses) can sig-
nificantly impact the performance of Prolog programs, and you are free to try different variants if you
use declarative approaches. Moreover, since all CLP(FD) constraints always terminate, placing them
earlier can at most improve, never worsen, the termination properties of your programs. An additional
benefit of CLP(FD) constraints is that they eliminate the complexity of introducing (is)/2 and
(=:=)/2 to beginners, since both predicates are subsumed by #=/2 when reasoning over integers.
A.8.6 Domains
Each CLP(FD) variable has an associated set of admissible integers, which we call the variables
domain. Initially, the domain of each CLP(FD) variable is the set of all integers. CLP(FD) constraints
like #=/2, #>/2 and #\=/2 can at most reduce, and never extend, the domains of their arguments.
The constraints in/2 and ins/2 let us explicitly state domains of CLP(FD) variables. The process of
determining and adjusting domains of variables is called constraint propagation, and it is performed
automatically by this library. When the domain of a variable contains only one element, then the
variable is automatically unified to that element.
Domains are taken into account when further constraints are stated, and by enumeration predicates
like labeling/2.
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
Sample query:
In this concrete case, the constraint solver is strong enough to find the unique solution without any
search.
?- X #> 3.
X in 4..sup.
?- X #\= 20.
X in inf..19\/21..sup.
?- 2*X #= 10.
X = 5.
?- X*X #= 144.
X in -12\/12.
Y = 6.
The answers emitted by the toplevel are called residual programs, and the goals that comprise
each answer are called residual goals. In each case above, and as for all pure programs, the residual
program is declaratively equivalent to the original query. From the residual goals, it is clear that the
constraint solver has deduced additional domain restrictions in many cases.
To inspect residual goals, it is best to let the toplevel display them for us. Wrap the call of your
predicate into call residue vars/2 to make sure that all constrained variables are displayed. To
make the constraints a variable is involved in available as a Prolog term for further reasoning within
your program, use copy term/3. For example:
This library also provides reflection predicates (like fd dom/2, fd size/2 etc.) with which
we can inspect a variables current domain. These predicates can be useful if you want to implement
your own labeling strategies.
2. Second, if the domain of each involved variable is finite, then enumeration predicates can be
used to search for concrete solutions.
It is good practice to keep the modeling part, via a dedicated predicate called the core relation,
separate from the actual search for solutions. This lets us observe termination and determinism prop-
erties of the core relation in isolation from the search, and more easily try different search strategies.
As an example of a constraint satisfaction problem, consider the cryptoarithmetic puzzle SEND +
MORE = MONEY, where different letters denote distinct integers between 0 and 9. It can be modeled
in CLP(FD) as follows:
Notice that we are not using labeling/2 in this predicate, so that we can first execute and
observe the modeling part in isolation. Sample query and its result (actual variables replaced for
readability):
?- puzzle(As+Bs=Cs).
As = [9, A2, A3, A4],
Bs = [1, 0, B3, A2],
Cs = [1, 0, A3, A2, C5],
A2 in 4..7,
all_different([9, A2, A3, A4, 1, 0, B3, C5]),
91*A2+A4+10*B3#=90*A3+C5,
A3 in 5..8,
A4 in 2..8,
B3 in 2..8,
C5 in 2..8.
From this answer, we see that this core relation terminates and is in fact deterministic. Moreover,
we see from the residual goals that the constraint solver has deduced more stringent bounds for all
variables. Such observations are only possible if modeling and search parts are cleanly separated.
Labeling can then be used to search for solutions in a separate predicate or goal:
?- puzzle(As+Bs=Cs), label(As).
As = [9, 5, 6, 7],
Bs = [1, 0, 8, 5],
Cs = [1, 0, 6, 5, 2] ;
false.
In this case, it suffices to label a subset of variables to find the puzzles unique solution, since the
constraint solver is strong enough to reduce the domains of remaining variables to singleton sets. In
general though, it is necessary to label all variables to obtain ground solutions.
In our concrete case, we observe that there must be exactly one queen per column. The following
representation therefore suggests itself: We are looking for 8 integers, one for each column, where
each integer denotes the row of the queen that is placed in the respective column, and which are subject
to certain constraints.
In fact, let us now generalize the task to the so-called N queens puzzle, which is obtained by re-
placing 8 by N everywhere it occurs in the above description. We implement the above considerations
in the core relation n_queens/2, where the first argument is the number of queens (which is iden-
tical to the number of rows and columns of the generalized chessboard), and the second argument is a
list of N integers that represents a solution in the form described above.
n_queens(N, Qs) :-
length(Qs, N),
Qs ins 1..N,
safe_queens(Qs).
safe_queens([]).
safe_queens([Q|Qs]) :- safe_queens(Qs, Q, 1), safe_queens(Qs).
safe_queens([], _, _).
safe_queens([Q|Qs], Q0, D0) :-
Q0 #\= Q,
abs(Q0 - Q) #\= D0,
D1 #= D0 + 1,
safe_queens(Qs, Q0, D1).
Note that all these predicates can be used in all directions: We can use them to find solutions, test
solutions and complete partially instantiated solutions.
The original task can be readily solved with the following query:
Using suitable labeling strategies, we can easily find solutions with 80 queens and more:
Experimenting with different search strategies is easy because we have separated the core relation
from the actual search.
A.8.11 Optimisation
We can use labeling/2 to minimize or maximize the value of a CLP(FD) expression, and generate
solutions in increasing or decreasing order of the value. See the labeling options min(Expr) and
max(Expr), respectively.
Again, to easily try different labeling options in connection with optimisation, we recommend to
introduce a dedicated predicate for posting constraints, and to use labeling/2 in a separate goal.
This way, we can observe properties of the core relation in isolation, and try different labeling options
without recompiling our code.
If necessary, we can use once/1 to commit to the first optimal solution. However, it is often
very valuable to see alternative solutions that are also optimal, so that we can choose among optimal
solutions by other criteria. For the sake of purity and completeness, we recommend to avoid once/1
and other constructs that lead to impurities in CLP(FD) programs.
Related to optimisation with CLP(FD) constraints are library(simplex) and CLP(Q) which
reason about linear constraints over rational numbers.
A.8.12 Reification
The constraints in/2, #=/2, #\=/2, #</2, #>/2, #=</2, and #>=/2 can be reified, which
means reflecting their truth values into Boolean values represented by the integers 0 and 1. Let P and
Q denote reifiable constraints or Boolean variables, then:
?- X #= 2, X = 1+1.
false.
?- X = 1+1, X #= 2, X = 1+1.
X = 1+1.
This behaviour is highly problematic from a logical point of view, and it may render declarative
debugging techniques inapplicable.
Set the Prolog flag clpfd_monotonic to true to make CLP(FD) monotonic: This means that
adding new constraints cannot yield new solutions. When this flag is true, we must wrap variables
that occur in arithmetic expressions with the functor (?)/1 or (#)/1. For example:
?- set_prolog_flag(clpfd_monotonic, true).
true.
?- X #= 2, X = 1+1.
ERROR: Arguments are not sufficiently instantiated
The wrapper can be omitted for variables that are already constrained to integers.
:- multifile clpfd:run_propagator/2.
oneground(X, Y, Z) :-
clpfd:make_propagator(oneground(X, Y, Z), Prop),
clpfd:init_propagator(X, Prop),
clpfd:init_propagator(Y, Prop),
clpfd:trigger_once(Prop).
?- oneground(X, Y, Z), Y = 5.
Y = 5,
Z = 1,
X in inf..sup.
A.8.15 Applications
CLP(FD) applications that we find particularly impressive and worth studying include:
Michael Hendricks uses CLP(FD) constraints for flexible reasoning about dates and times in
the julian package.
A.8.16 Acknowledgments
This library gives you a glimpse of what SICStus Prolog can do. The API is intentionally mostly
compatible with that of SICStus Prolog, so that you can easily switch to a much more feature-rich
and much faster CLP(FD) system when you need it. I thank Mats Carlsson, the designer and main
implementor of SICStus Prolog, for his elegant example. I first encountered his system as part of the
excellent GUPU teaching environment by Ulrich Neumerkel. Ulrich was also the first and most de-
termined tester of the present system, filing hundreds of comments and suggestions for improvement.
Tom Schrijvers has contributed several constraint libraries to SWI-Prolog, and I learned a lot from his
coding style and implementation examples. Bart Demoen was a driving force behind the implemen-
tation of attributed variables in SWI-Prolog, and this library could not even have started without his
prior work and contributions. Thank you all!
Arithmetic constraints
Arithmetic constraints are the most basic use of CLP(FD). Every time you use (is)/2 or one of
the low-level arithmetic comparisons ((<)/2, (>)/2 etc.) over integers, consider using CLP(FD)
constraints instead. This can at most increase the generality of your programs. See declarative integer
arithmetic (section A.8.3).
?X #= ?Y
The arithmetic expression X equals Y. This is the most important arithmetic constraint (sec-
tion A.8.2), subsuming and replacing both (is)/2 and (=:=)/2 over integers. See
declarative integer arithmetic (section A.8.3).
?X #\= ?Y
The arithmetic expressions X and Y evaluate to distinct integers. When reasoning over integers,
replace (=\=)/2 by #\=/2 to obtain more general relations. See declarative integer
arithmetic (section A.8.3).
?X #>= ?Y
Same as Y #=< X. When reasoning over integers, replace (>=)/2 by #>=/2 to obtain more
general relations. See declarative integer arithmetic (section A.8.3).
?X #=< ?Y
The arithmetic expression X is less than or equal to Y. When reasoning over integers, replace
(=<)/2 by #=</2 to obtain more general relations. See declarative integer arithmetic
(section A.8.3).
?X #> ?Y
Same as Y #< X. When reasoning over integers, replace (>)/2 by #>/2 to obtain more
general relations See declarative integer arithmetic (section A.8.3).
?X #< ?Y
The arithmetic expression X is less than Y. When reasoning over integers, replace (<)/2 by
#</2 to obtain more general relations. See declarative integer arithmetic (section A.8.3).
In addition to its regular use in tasks that require it, this constraint can also be useful to eliminate
uninteresting symmetries from a problem. For example, all possible matches between pairs built
from four players in total:
Membership constraints
If you are using CLP(FD) to model and solve combinatorial tasks, then you typically need to specify
the admissible domains of variables. The membership constraints in/2 and ins/2 are useful in
such cases.
?Var in +Domain
Var is an element of Domain. Domain is one of:
Integer
Singleton set consisting only of Integer.
Lower .. Upper
All integers I such that Lower =< I =< Upper. Lower must be an integer or the atom inf,
which denotes negative infinity. Upper must be an integer or the atom sup, which denotes
positive infinity.
Domain1 \/ Domain2
The union of Domain1 and Domain2.
Enumeration predicates
When modeling combinatorial tasks, the actual search for solutions is typically performed by enu-
meration predicates like labeling/2. See the the section about core relations and search for more
information.
indomain(?Var)
Bind Var to all feasible values of its domain on backtracking. The domain of Var must be finite.
label(+Vars)
Equivalent to labeling([], Vars). See labeling/2.
labeling(+Options, +Vars)
Assign a value to each variable in Vars. Labeling means systematically trying out values for
the finite domain variables Vars until all of them are ground. The domain of each variable in
Vars must be finite. Options is a list of options that let you exhibit some control over the search
process. Several categories of options exist:
The variable selection strategy lets you specify which variable of Vars is labeled next and is one
of:
leftmost
Label the variables in the order they occur in Vars. This is the default.
ff
First fail. Label the leftmost variable with smallest domain next, in order to detect infea-
sibility early. This is often a good strategy.
ffc
Of the variables with smallest domains, the leftmost one participating in most constraints
is labeled next.
min
Label the leftmost variable whose lower bound is the lowest next.
max
Label the leftmost variable whose upper bound is the highest next.
up
Try the elements of the chosen variables domain in ascending order. This is the default.
down
Try the domain elements in descending order.
step
For each variable X, a choice is made between X = V and X #\= V, where V is determined
by the value ordering options. This is the default.
enum
For each variable X, a choice is made between X = V 1, X = V 2 etc., for all values V i
of the domain of X. The order is determined by the value ordering options.
bisect
For each variable X, a choice is made between X #=< M and X #> M, where M is the
midpoint of the domain of X.
At most one option of each category can be specified, and an option must not occur repeatedly.
The order of solutions can be influenced with:
min(Expr)
max(Expr)
This generates solutions in ascending/descending order with respect to the evaluation of the
arithmetic expression Expr. Labeling Vars must make Expr ground. If several such options are
specified, they are interpreted from left to right, e.g.:
This generates solutions in descending order of X, and for each binding of X, solutions are
generated in ascending order of Y. To obtain the incomplete behaviour that other systems exhibit
with maximize(Expr) and minimize(Expr), use once/1, e.g.:
once(labeling([max(Expr)], Vars))
Labeling is always complete, always terminates, and yields no redundant solutions. See core
relations and search (section A.8.9) for usage advice.
Global constraints
A global constraint expresses a relation that involves many variables at once. The most fre-
quently used global constraints of this library are the combinatorial constraints all distinct/1,
global cardinality/2 and cumulative/2.
all distinct(+Vars)
True iff Vars are pairwise distinct. For example, all distinct/1 can detect that not all
variables can assume distinct values given the following domains:
?- maplist(in, Vs,
[1\/3..4, 1..2\/4, 1..2\/4, 1..3, 1..3, 1..6]),
all_distinct(Vs).
false.
all different(+Vars)
Like all distinct/1, but with weaker propagation. Consider using all distinct/1
instead, since all distinct/1 is typically acceptably efficient and propagates much more
strongly.
lex chain(+Lists)
Lists are lexicographically non-decreasing.
?- tuples_in([[X,Y]], [[1,2],[1,5],[4,0],[4,3]]), X = 4.
X = 4,
Y in 0\/3.
trains([[1,2,0,1],
[2,3,4,5],
[2,3,0,1],
[3,4,5,6],
[3,4,2,3],
[3,4,8,9]]).
threepath(A, D, Ps) :-
Ps = [[A,B,_T0,T1],[B,C,T2,T3],[C,D,T4,_T5]],
T2 #> T1,
T4 #> T3,
trains(Ts),
tuples_in(Ps, Ts).
?- threepath(1, 4, Ps).
Ps = [[1, 2, 0, 1], [2, 3, 4, 5], [3, 4, 8, 9]].
serialized(+Starts, +Durations)
Describes a set of non-overlapping tasks. Starts = [S 1,...,S n], is a list of variables or integers,
Durations = [D 1,...,D n] is a list of non-negative integers. Constrains Starts and Durations to
denote a set of non-overlapping tasks, i.e.: S i + D i =< S j or S j + D j =< S i for all 1 =< i <
j =< n. Example:
?- length(Vs, 3),
Vs ins 0..3,
serialized(Vs, [1,2,3]),
label(Vs).
Vs = [0, 1, 3] ;
Vs = [2, 0, 3] ;
false.
See also Dorndorf et al. 2000, Constraint Propagation Techniques for the Disjunctive Scheduling
Problem
consistency(value)
A weaker form of consistency is used.
cost(Cost, Matrix)
Matrix is a list of rows, one for each variable, in the order they occur in Vs. Each of these
rows is a list of integers, one for each key, in the order these keys occur in Pairs. When
variable v i is assigned the value of key k j, then the associated cost is Matrix {ij}. Cost
is the sum of all costs.
circuit(+Vs)
True iff the list Vs of finite domain variables induces a Hamiltonian circuit. The k-th element
of Vs denotes the successor of node k. Node indexing starts with 1. Examples:
cumulative(+Tasks)
Equivalent to cumulative(Tasks, [limit(1)]). See cumulative/2.
cumulative(+Tasks, +Options)
Schedule with a limited resource. Tasks is a list of tasks, each of the form
task(S_i, D_i, E_i, C_i, T_i). S i denotes the start time, D i the positive
duration, E i the end time, C i the non-negative resource consumption, and T i the task
identifier. Each of these arguments must be a finite domain variable with bounded domain, or
an integer. The constraint holds iff at each time slot during the start and end of each task, the
total resource consumption of all tasks running at that time does not exceed the global resource
limit. Options is a list of options. Currently, the only supported option is:
limit(L)
The integer L is the global resource limit. Default is 1.
For example, given the following predicate that relates three tasks of durations 2 and 3 to a list
containing their starting times:
tasks_starts(Tasks, [S1,S2,S3]) :-
Tasks = [task(S1,3,_,1,_),
task(S2,2,_,1,_),
task(S3,2,_,1,_)].
disjoint2(+Rectangles)
True iff Rectangles are not overlapping. Rectangles is a list of terms of the form F(X i, W i,
Y i, H i), where F is any functor, and the arguments are finite domain variables or integers that
denote, respectively, the X coordinate, width, Y coordinate and height of each rectangle.
two_consecutive_ones(Vs) :-
automaton(Vs, [source(a),sink(c)],
[arc(a,0,a), arc(a,1,b),
arc(b,0,a), arc(b,1,c),
arc(c,0,c), arc(c,1,c)]).
Example query:
sequence_inflexions(Vs, N) :-
variables_signature(Vs, Sigs),
automaton(Sigs, _, Sigs,
[source(s),sink(i),sink(j),sink(s)],
[arc(s,0,s), arc(s,1,j), arc(s,2,i),
arc(i,0,i), arc(i,1,j,[C+1]), arc(i,2,i),
arc(j,0,j), arc(j,1,j),
arc(j,2,i,[C+1])],
[C], [0], [N]).
variables_signature([], []).
variables_signature([V|Vs], Sigs) :-
variables_signature_(Vs, V, Sigs).
variables_signature_([], _, []).
variables_signature_([V|Vs], Prev, [S|Sigs]) :-
V #= Prev #<==> S #= 0,
Prev #< V #<==> S #= 1,
Prev #> V #<==> S #= 2,
variables_signature_(Vs, V, Sigs).
Example queries:
?- sequence_inflexions([1,2,3,3,2,1,3,0], N).
N = 3.
chain(+Zs, +Relation)
Zs form a chain with respect to Relation. Zs is a list of finite domain variables that are a chain
with respect to the partial order Relation, in the order they appear in the list. Relation must be
#=, #=<, #>=, #< or #>. For example:
?- chain([X,Y,Z], #>=).
X#>=Y,
Y#>=Z.
Reification predicates
Many CLP(FD) constraints can be reified. This means that their truth value is itself turned into a
CLP(FD) variable, so that we can explicitly reason about whether a constraint holds or not. See
reification (section A.8.12).
#\ +Q
Q does not hold. See reification (section A.8.12).
For example, to obtain the complement of a domain:
?- #\ X in -3..0\/10..80.
X in inf.. -4\/1..9\/81..sup.
?P #<==> ?Q
P and Q are equivalent. See reification (section A.8.12).
For example:
?- X #= 4 #<==> B, X #\= 4.
B = 0,
X in inf..3\/5..sup.
The following example uses reified constraints to relate a list of finite domain variables to the
number of occurrences of a given value:
vs_n_num(Vs, N, Num) :-
maplist(eq_b(N), Vs, Bs),
sum(Bs, #=, Num).
eq_b(X, Y, B) :- X #= Y #<==> B.
?- vs_n_num([X,Y,Z], 2, 3).
X = 2,
Y = 2,
Z = 2.
?P #==> ?Q
P implies Q. See reification (section A.8.12).
?P #<== ?Q
Q implies P. See reification (section A.8.12).
?P #/\ ?Q
P and Q hold. See reification (section A.8.12).
?P #\/ ?Q
P or Q holds. See reification (section A.8.12).
For example, the sum of natural numbers below 1000 that are multiples of 3 or 5:
Ns),
sum(Ns, #=, Sum).
Ns = [0, 3, 5, 6, 9, 10, 12, 15, 18|...],
Sum = 233168.
?P #\ ?Q
Either P holds or Q holds, but not both. See reification (section A.8.12).
n_factorial(N, F) :-
zcompare(C, N, 0),
n_factorial_(C, N, F).
n_factorial_(=, _, 1).
n_factorial_(>, N, F) :-
F #= F0*N, N1 #= N - 1,
n_factorial(N1, F0).
This version is deterministic if the first argument is instantiated, because first argument indexing
can distinguish the two different clauses:
?- n_factorial(30, F).
F = 265252859812191058636308480000000.
The predicate can still be used in all directions, including the most general query:
?- n_factorial(N, F).
N = 0,
F = 1 ;
N = F, F = 1 ;
N = F, F = 2 .
Reflection predicates
Reflection predicates let us obtain, in a well-defined way, information that is normally internal to this
library. In addition to the predicates explained below, also take a look at call residue vars/2
and copy term/3 to reason about CLP(FD) constraints that arise in programs. This can be useful
in program analyzers and declarative debuggers.
fd var(+Var)
True iff Var is a CLP(FD) variable.
fd inf(+Var, -Inf)
Inf is the infimum of the current domain of Var.
fd sup(+Var, -Sup)
Sup is the supremum of the current domain of Var.
fd size(+Var, -Size)
Reflect the current size of a domain. Size is the number of elements of the current domain of
Var, or the atom sup if the domain is unbounded.
fd dom(+Var, -Dom)
Dom is the current domain (see in/2) of Var. This predicate is useful if you want to reason
about domains. It is not needed if you only want to display remaining domains; instead,
separate your model from the search part and let the toplevel display this information via
residual goals.
For example, to implement a custom labeling strategy, you may need to inspect the current
domain of a finite domain variable. With the following code, you can convert a finite domain to
a list of integers:
Example:
This CLP(Q,R) system is a port of the CLP(Q,R) system of Sicstus Prolog by Christian Holzbaur:
Holzbaur C.: OFAI clp(q,r) Manual, Edition 1.3.3, Austrian Research Institute for Artificial Intelli-
gence, Vienna, TR-95-09, 1995.1 This manual is roughly based on the manual of the above mentioned
CLP(Q,R) implementation.
The CLP(Q,R) system consists of two components: the CLP(Q) library for handling constraints
over the rational numbers and the CLP(R) library for handling constraints over the real numbers (using
floating point numbers as representation). Both libraries offer the same predicates (with exception of
bb inf/4 in CLP(Q) and bb inf/5 in CLP(R)). It is allowed to use both libraries in one program,
but using both CLP(Q) and CLP(R) constraints on the same variable will result in an exception.
Please note that the clpqr library is not an autoload library and therefore this library must be
loaded explicitly before using it:
:- use_module(library(clpq)).
or
:- use_module(library(clpr)).
{}(+Constraints)
Adds the constraints given by Constraints to the constraint store.
entailed(+Constraint)
Succeeds if Constraint is necessarily true within the current constraint store. This means that
adding the negation of the constraint to the store results in failure.
inf(+Expression, -Inf)
Computes the infimum of Expression within the current state of the constraint store and returns
that infimum in Inf. This predicate does not change the constraint store.
sup(+Expression, -Sup)
Computes the supremum of Expression within the current state of the constraint store and
returns that supremum in Sup. This predicate does not change the constraint store.
minimize(+Expression)
Minimizes Expression within the current constraint store. This is the same as computing the
infimum and equating the expression to that infimum.
1
http://www.ai.univie.ac.at/cgi-bin/tr-online?number+95-09
maximize(+Expression)
Maximizes Expression within the current constraint store. This is the same as computing the
supremum and equating the expression to that supremum.
dump([X,Y,Z],[x,y,z],Cons)
Cons will contain the constraints on X, Y and Z, where these variables have been replaced by
atoms x, y and z.
Unification
{X =:= Y} with a variable
{X = Y}
X = Y
Unification
{X =:= 5.0} with a number
{X = 5.0}
X = 5.0
A=BC B or C is ground A = 5 * C or A = B * 4
A and (B or C) are ground 20 = 5 * C or 20 = B * 4
A = B/C C is ground A=B/3
A and B are ground 4 = 12 / C
X = min(Y, Z) Y and Z are ground X = min(4,3)
X = max(Y, Z) Y and Z are ground X = max(4,3)
X = abs(Y ) Y is ground X = abs(-7)
X = pow(Y, Z) X and Y are ground 8=2Z
X = exp(Y, Z) X and Z are ground 8=Y3
X =Y Z Y and Z are ground X=23
X = sin(Y ) X is ground 1 = sin(Y)
X = cos(Y ) Y is ground X = sin(1.5707)
X = tan(Y )
Top-level output
The top-level output may contain variables not present in the original query:
?- {X+Y>=1}.
{Y=1-X+_G2160, _G2160>=0}.
?-
Nonetheless, for linear constraints this kind of answer means unconditional satisfiability.
Dumping constraints
The first argument of dump/3 has to be a list of free variables at call-time:
?- {X=1},dump([X],[Y],L).
ERROR: Unhandled exception: Unknown message:
instantiation_error(dump([1],[_G11],_G6),1)
?-
This library parses and generates CSV data. CSV data is represented in Prolog as a list of rows.
Each row is a compound term, where all rows have the same name and arity.
csv(?Rows) // [det]
csv(?Rows, +Options) // [det]
Prolog DCG to read/write CSV data. Options:
separator(+Code)
The comma-separator. Must be a character code. Default is (of course) the comma.
Character codes can be specified using the 0 notion. E.g., using separator(0;)
parses a semicolon separated file.
ignore quotes(+Boolean)
If true (default false), threat double quotes as a normal character.
strip(+Boolean)
If true (default false), strip leading and trailing blank space. RFC4180 says that
blank space is part of the data.
convert(+Boolean)
If true (default), use name/2 on the field data. This translates the field into a number if
possible.
functor(+Atom)
Functor to use for creating row terms. Default is row.
arity(?Arity)
Number of fields in each row. This predicate raises a
domain_error(row_arity(Expected), Found) if a row is found with
different arity.
match arity(+Boolean)
If false (default true), do not reject CSV files where lines provide a varying number
of fields (columns). This can be a work-around to use some incorrect CSV files.
line(-Line)
Line is unified with the 1-based line-number from which Row is read. Note that Line is
not the physical line, but rather the logical record number.
To be done Input is read line by line. If a record separator is embedded in a quoted field, parsing the
record fails and another line is added to the input. This does not nicely deal with other reasons
why parsing the row may fail.
save_data(File) :-
setup_call_cleanup(
open(File, write, Out),
forall(data(C1,C2,C3),
csv_write_stream(Out, [row(C1,C2,C3)], [])),
close(Out)),
This library is a replacement for format/3 for printing debug messages. Messages are assigned
a topic. By dynamically enabling or disabling topics the user can select desired messages. Debug
statements are removed when the code is compiled for optimization.
See manual for details. With XPCE, you can use the call below to start a graphical monitoring
tool.
?- prolog_ide(debug_monitor).
Using the predicate assertion/1 you can make assumptions about your program explicit,
trapping the debugger if the condition does not hold.
debugging(+Topic) [semidet]
debugging(-Topic) [nondet]
debugging(?Topic, ?Bool) [nondet]
Examine debug topics. The form debugging(+Topic) may be used to perform more
complex debugging tasks. A typical usage skeleton is:
( debugging(mytopic)
-> <perform debugging actions>
; true
),
...
The other two calls are intended to examine existing and enabled debugging tokens and are
typically not used in user programs.
debug(+Topic) [det]
nodebug(+Topic) [det]
Add/remove a topic from being printed. nodebug(_) removes all topics. Gives a warning if
the topic is not defined unless it is used from a directive. The latter allows placing debug topics
at the start of a (load-)file without warnings.
For debug/1, Topic can be a term Topic > Out, where Out is either a stream or stream-alias
or a filename (atom). This redirects debug information on this topic to the given output.
?- prolog_ide(debug_monitor).
assertion(:Goal) [det]
Acts similar to C assert() macro. It has no effect if Goal succeeds. If Goal fails or throws
an exception, the following steps are taken:
This module provides predicates to simplify error generation and checking. Its implementation
is based on a discussion on the SWI-Prolog mailinglist on best practices in error handling. The utility
predicate must be/2 provides simple run-time type validation. The * error predicates are simple
wrappers around throw/1 to simplify throwing the most common ISO error terms.
error. Most Prolog programmers consider each compound as a type and would consider a
compoint that is not point(_,_) a type error.
domain error(+Type, +Term)
The argument is of the proper type, but has a value that is outside the supported values. See
type error/2 for a more elaborate discussion of the distinction between type- and
domain-errors.
existence error(+Type, +Term)
Term is of the correct type and correct domain, but there is no existing (external) resource that
is represented by it.
permission error(+Action, +Type, +Term)
It is not allowed to perform Action on the object Term that is of the given Type.
instantiation error(+Term)
An argument is under-instantiated. I.e. it is not acceptable as it is, but if some variables are
bound to appropriate values it would be acceptable.
Arguments
Term is the term that needs (further) instantiation. Unfortunately, the
ISO error does not allow for passing this term along with the error,
but we pass it to this predicate for documentation purposes and to
allow for future enhancement.
uninstantiation error(+Term)
An argument is over-instantiated. This error is used for output arguments whose value cannot
be known upfront. For example, the goal open(File, read, input) cannot succeed
because the system will allocate a new unique stream handle that will never unify with input.
representation error(+Reason)
A representation error indicates a limitation of the implementation. SWI-Prolog has no such
limits that are not covered by other errors, but an example of a representation error in another
Prolog implementation could be an attempt to create a term with an arity higher than supported
by the system.
syntax error(+Culprit)
A text has invalid syntax. The error is described by Culprit.
To be done Deal with proper description of the location of the error. For short texts, we allow for
Type(Text), meaning Text is not a valid Type. E.g. syntax_error(number(1a)) means
that 1a is not a valid number.
resource error(+Culprit)
A goal cannot be completed due to lack of resources.
must be(+Type, @Term) [det]
True if Term satisfies the type constraints for Type. Defined types are atom, atomic,
between, boolean, callable, chars, codes, text, compound, constant,
float, integer, nonneg, positive_integer, negative_integer, nonvar,
number, oneof, list, list_or_partial_list, symbol, var, rational,
encoding, dict and string.
Most of these types are defined by an arity-1 built-in predicate of the same name. Below is a
brief definition of the other types.
Note: The Windows version can only represent Unicode code points up to 216-1. Higher
values cause a representation error on most text handling predicates.
gensym(+Base, -Unique)
Generate a unique atom from base Base and unify it with Unique. Base should be an atom. The
first call will return hbasei1, the next hbasei2, etc. Note that this is no guarantee that the atom
is unique in the system.
reset gensym(+Base)
Restart generation of identifiers from Base at hBasei1. Used to make sure a program produces
the same results on subsequent runs. Use with care.
reset gensym
Reset gensym for all registered keys. This predicate is available for compatibility only. New
code is strongly advised to avoid the use of reset gensym or at least to reset only the keys used
by your program to avoid unexpected side effects on other components.
This library contains utilities that deal with streams, notably originating from non-built-in sources
such as URLs, archives, windows, processes, etc.
The predicate open any/5 acts as a broker between applications that can process data from a
stream and libraries that can create streams from diverse sources. Without this predicate, processing
data inevitally follows the pattern below. As call some open variation can be anything, this blocks
us from writing predicates such as load_xml(From, DOM) that can operate on arbitrary input
sources.
setup_call_cleanup(
call_some_open_variation(Spec, In),
process(In),
close(In)).
Libraries that can open streams can install the hook iostream:open hook/6 to make their
functionality available through open any/5.
encoding(Enc)
Set stream to encoding Enc.
Without loaded plugins, the open any/5 processes the following values for Specification. If
no rule matches, open any/5 processes Specification as file(Specification).
Stream
A plain stream handle. Possisible post-processing options such as encoding are applied.
Close does not close the stream, but resets other side-effects such as the encoding.
stream(Stream)
Same as a plain Stream.
FileURL
If Specification is of the form =file://...=, the pointed to file is opened using open/4.
Requires library(uri) to be installed.
file(Path)
Explicitly open the file Path. Path can be an Path(File) term as accepted by
absolute file name/3.
string(String)
Open a Prolog string, atom, list of characters or codes as an input stream.
The typical usage scenario is given in the code below, where <process> processes the input.
setup_call_cleanup(
open_any(Spec, read, In, Close, Options),
<process>(In),
Close).
library(http/http open)
Adds support for URLs using the http and https schemes.
close any(+Goal)
Execute the Close closure returned by open any/5. The closure can also be called directly.
Using close any/1 can be considered better style and enhances tractability of the source
code.
This library provides commonly accepted basic predicates for list manipulation in the Prolog
community. Some additional list manipulations are built-in. See e.g., memberchk/2, length/2.
The implementation of this library is copied from many places. These include: The Craft of
Prolog, the DEC-10 Prolog library (LISTRO.PL) and the YAP lists library. Some predicates are
reimplemented based on their specification by Quintus and SICStus.
member(?Elem, ?List)
True if Elem is a member of List. The SWI-Prolog definition differs from the classical one.
Our definition avoids unpacking each list element twice and provides determinism on the last
element. E.g. this is deterministic:
member(X, [One]).
append(+ListOfLists, ?List)
Concatenate a list of lists. Is true if ListOfLists is a list of lists, and List is the concatenation of
these lists.
Arguments
ListOfLists must be a list of possibly partial lists
prefix(?Part, ?Whole)
True iff Part is a leading substring of Whole. This is the same as
append(Part, _, Whole).
last(?List, ?Last)
Succeeds when Last is the last element of List. This predicate is semidet if List is a list and
multi if List is a partial list.
Compatibility There is no de-facto standard for the argument order of last/2. Be careful when
porting code or use append(_, [Last], List) as a portable alternative.
proper_length(List, Length) :-
is_list(List),
length(List, Length).
reverse(?List1, ?List2)
Is true when the elements of List2 are in reverse order compared to List1.
is_permutation(Xs, Ys) :-
msort(Xs, Sorted),
msort(Ys, Sorted).
The example below illustrates that Xs and Ys being proper lists is not a sufficient condition to
use the above replacement.
?- permutation([1,2], [X,Y]).
X = 1, Y = 2 ;
X = 2, Y = 1 ;
false.
See also
- compare/3
- max list/2 for the maximum of a list of numbers.
See also
- compare/3
- min list/2 for the minimum of a list of numbers.
Errors
- type_error(integer, Low)
- type_error(integer, High)
is set(@Set) [semidet]
True if Set is a proper list without duplicates. Equivalence is based on ==/2. The implemen-
tation uses sort/2, which implies that the complexity is N*log(N) and the predicate may
cause a resource-error. There are no other error conditions.
generate_and_test(Solution) :-
empty_nb_set(Set),
generate(Solution),
add_nb_set(Solution, Set, true),
test(Solution).
empty nb set(?Set)
True if Set is a non-backtrackable empty set.
MS-Windows
If it detects MS-Windows it uses win shell/2 to open the URL. The behaviour and
browser started depends on the version of Windows and Windows-shell configuration, but
in general it should be the behaviour expected by the user.
Other platforms
On other platforms it tests the environment variable (see getenv/2) named BROWSER
or uses netscape if this variable is not set. If the browser is either mozilla or
netscape, www open url/1 first tries to open a new window on a running browser
using the -remote option of Netscape. If this fails or the browser is not mozilla or
netscape the system simply passes the URL as first argument to the program.
To be done We should consider putting many options in an assoc or record with appropriate preprocessing
to achieve better performance.
The library(option) provides some utilities for processing option lists. Option lists are
commonly used as an alternative for many arguments. Examples of built-in predicates are open/4
and write term/3. Naming the arguments results in more readable code, and the list nature makes
it easy to extend the list of options accepted by a predicate. Option lists come in two styles, both of
which are handled by this library.
Processing options inside time-critical code (loops) can cause serious overhead. One possibility is
to define a record using library(record) and initialise this using make <record>/2. In addition
to providing good performance, this also provides type-checking and central declaration of defaults.
process(Data, Options) :-
make_atts(Options, Attributes),
action(Data, Attributes).
action(Data, Attributes) :-
atts_shape(Attributes, Shape),
...
Options typically have exactly one argument. The library does support options with 0 or more
than one argument with the following restrictions:
The predicate option/3 and select option/4, involving default are meaningless. They
perform an arg(1, Option, Default), causing failure without arguments and filling
only the first option-argument otherwise.
meta options/3 can only qualify options with exactly one argument.
is_meta(callback).
Meta-options must have exactly one argument. This argument will be qualified.
Dict keys can be integers. This is not allowed in canonical option lists.
Options can hold multiple options with the same key. This is not allowed in dicts.
Options can have more than one value (name(V1,V2)). This is not allowed in dicts.
Also note that most system predicates and predicates using this library for processing the option
argument can both work with classical Prolog options and dicts objects.
runtime arguments, which controls the prolog runtime; conventionally, they are ended by ;
options, which are key-value pairs (with a boolean value possibly implicit) intended to control
your program in one way or another; and
positional arguments, which is what remains after all runtime arguments and options have been
removed (with implicit arguments true/false for booleans filled in).
Positional arguments are in particular used for mandatory arguments without which your program
wont work and for which there are no sensible defaults (e.g,, input file names). Options, by contrast,
offer flexibility by letting you change a default setting. Options are optional not only by etymology:
this library has no notion of mandatory or required options (see the python docs for other rationales
than laziness).
The command-line arguments enter your program as a list of atoms, but the programs perhaps
expects booleans, integers, floats or even prolog terms. You tell the parser so by providing an options
specification. This is just a list of individual option specifications. One of those, in turn, is a list of
ground prolog terms in the customary Name(Value) format. The following terms are recognized (any
others raise error).
opt(Key)
Key is what the option later will be accessed by, just like for
current_prolog_flag(Key, Value). This term is mandatory (an error is thrown if
missing).
shortflags(ListOfFlags)
ListOfFlags denotes any single-dashed, single letter args specifying the current option
(-s , -K, etc). Uppercase letters must be quoted. Usually ListOfFlags will be a singleton
list, but sometimes aliased flags may be convenient.
longflags(ListOfFlags)
ListOfFlags denotes any double-dashed arguments specifying the current option
(--verbose, --no-debug, etc). They are basically a more readable alternative to
short flags, except
meta(Meta)
Meta is optional and only relevant for the synthesized usage message and is the name (an atom)
of the metasyntactic variable (possibly) appearing in it together with type and default value
(e.g, x:integer=3, interest:float=0.11). It may be useful to have named variables
(x, interest) in case you wish to mention them again in the help text. If not given the
Meta: part is suppressed see example below.
type(Type)
Type is one of boolean, atom, integer, float, term. The corresponding argu-
ment will be parsed appropriately. This term is optional; if not given, defaults to term.
default(Default)
Default value. This term is optional; if not given, or if given the special value , an uninstan-
tiated variable is created (and any type declaration is ignored).
help(Help)
Help is (usually) an atom of text describing the option in the help text. This term is optional
(but obviously strongly recommended for all options which have flags).
Long lines are subject to basic word wrapping split on white space, reindent, rejoin. However,
you can get more control by supplying the line breaking yourself: rather than a single line of
text, you can provide a list of lines (as atoms). If you do, they will be joined with the appropriate
indent but otherwise left untouched (see the option mode in the example below).
Absence of mandatory option specs or the presence of more than one for a particular option throws
an error, as do unknown or incompatible types.
As a concrete example from a fictive application, suppose we want the following options to be
read from the command line (long flag(s), short flag(s), meta:type=default, help)
iterations
--distances term=[1,2,3,5] initial prolog term
--output-file -o FILE:atom=_ write output to FILE
--label -l atom=REPORT report label
--verbosity -v V:integer=2 verbosity level,
1 <= V <= 3
We may also have some configuration parameters which we currently think not needs to be con-
trolled from the command line, say path(/some/file/path).
This interface is described by the following options specification (order between the specifications
of a particular option is irrelevant).
ExampleOptsSpec =
[ [opt(mode ), type(atom), default(SCAN),
shortflags([m]), longflags([mode] ),
help([ data gathering mode, one of
, SCAN: do this
, READ: do that
, MAKE: fabricate some numbers
, WAIT: dont do anything])]
, [opt(distances), default([1,2,3,5]),
longflags([distances]),
help(initial prolog term)]
, [opt(path), default(/some/file/path/)]
].
ExampleArgs = [ -d5
, --heisenberg-threshold, 0.14
, --distances=[1,1,2,3,5,8]
, --iters, 7
, -ooutput.txt
, --rebuild-cache, true
, input.txt
, --verbosity=2
].
Opts = [ mode(SCAN)
, label(REPORT)
, path(/some/file/path)
, threshold(0.14)
, distances([1,1,2,3,5,8])
, depth(7)
, outfile(output.txt)
, cache(true)
, verbose(2)
],
PositionalArgs = [input.txt].
Note that path(/some/file/path) showing up in Opts has a default value (of the im-
plicit type term), but no corresponding flags in OptsSpec. Thus it cant be set from the command
line. The rest of your program doesnt need to know that, of course. This provides an alternative
to the common practice of asserting such hard-coded parameters under a single predicate (for in-
stance setting(path, /some/file/path)), with the advantage that you may seamlessly
upgrade them to command-line options, should you one day find this a good idea. Just add an ap-
propriate flag or two and a line of help text. Similarly, suppressing an option in a cluttered interface
amounts to commenting out the flags.
opt parse/5 allows more control through an additional argument list as shown in the example
below.
This representation may be preferable with the empty-flag configuration parameter style above
(perhaps with asserting appl config/2).
Note that -sbar is taken to mean -s bar, not -s -b -a -r, that is, there is no clustering
of flags.
-s=foo is disallowed. The rationale is that although some command-line parsers will silently
interpret this as -s =foo, this is very seldom what you want. To have an option argument start
with = (very un-recommended), say so explicitly.
The example specifies the option depth twice: once as -d5 and once as --iters 7. The
default when encountering duplicated flags is to keeplast (this behaviour can be controlled,
by ParseOption duplicated flags).
The order of the options returned by the parsing functions is the same as given on the command
line, with non-overridden defaults prepended and duplicates removed as in previous item. You
should not rely on this, however.
Unknown flags (not appearing in OptsSpec) will throw errors. This is usually a Good Thing.
Sometimes, however, you may wish to pass along flags to an external program (say, one called
by shell/2), and it means duplicated effort and a maintenance headache to have to specify
all possible flags for the external program explicitly (if it even can be done). On the other
hand, simply taking all unknown flags as valid makes error checking much less efficient and
identification of positional arguments uncertain. A better solution is to collect all arguments
intended for passing along to an indirectly called program as a single argument, probably as an
atom (if you dont need to inspect them first) or as a prolog term (if you do).
that command-line arguments can be accessed by current prolog flag/2 (as in swi-
prolog). For other access mechanisms and/or more control, get the args and pass them as a list
of atoms to opt parse/4 or opt parse/5 instead.
Opts is a list of parsed options in the form Key(Value). Dashed args not in OptsSpec are not
permitted and will raise error (see tip on how to pass unknown flags in the module description).
PositionalArgs are the remaining non-dashed args after each flag has taken its argument (filling
in true or false for booleans). There are no restrictions on non-dashed arguments and they
may go anywhere (although it is good practice to put them last). Any leading arguments for the
runtime (up to and including ) are discarded.
output functor(Func)
Set the functor Func of the returned options Func(Key,Value). Default is the special value
OPTION (upper-case), which makes the returned options have form Key(Value).
duplicated flags(Keep)
Controls how to handle options given more than once on the commad line. Keep is
one of keepfirst, keeplast, keepall with the obvious meaning. Default is
keeplast.
allow empty flag spec(Bool)
If true (default), a flag specification is not required (it is allowed that both shortflags
and longflags be either [] or absent). Flagless options cannot be manipulated from the
command line and will not show up in the generated help. This is useful when you have
(also) general configuration parameters in your OptsSpec, especially if you think they
one day might need to be controlled externally. See example in the module overview.
allow_empty_flag_spec(false) gives the more customary behaviour of raising
error on empty flags.
is ordset(@Term) [semidet]
True if Term is an ordered set. All predicates in this library expect ordered sets as input argu-
ments. Failing to fullfil this assumption results in undefined behaviour. Typically, ordered sets
are created by predicates from this library, sort/2 or setof/3.
Compatibility sicstus
Compatibility sicstus
For example:
This module implements common operations on Key-Value lists, also known as Pairs. Pairs have
great practical value, especially due to keysort/2 and the library assoc.pl.
This library is based on disussion in the SWI-Prolog mailinglist, including specifications from
Quintus and a library proposal by Richard OKeefe.
Sorting the list of pairs before grouping can be used to group all values associated with a key.
For example, finding all values associated with the largest key:
In this example, sorting by key only (first argument of sort/4 is 1) ensures that the order of
the values in the original list of pairs is maintained.
Arguments
Pairs Key-Value list
Joined List of Key-Group, where Group is the list of Values associated
with equivalent consecutive Keys in the same order as they appear
in Pairs.
This module provides simple persistent storage for one or more dynamic predicates. A database
is always associated with a module. A module that wishes to maintain a database must declare the
terms that can be placed in the database using the directive persistent/1.
The persistent/1 expands each declaration into four predicates:
name(Arg, ...)
assert_name(Arg, ...)
retract_name(Arg, ...)
retractall_name(Arg, ...)
As mentioned, a database can only be accessed from within a single module. This limitation is on
purpose, forcing the user to provide a proper API for accessing the shared persistent data.
Below is a simple example:
:- module(user_db,
[ attach_user_db/1, % +File
current_user_role/2, % ?User, ?Role
add_user/2, % +User, +Role
set_user_role/2 % +User, +Role
]).
:- use_module(library(persistency)).
:- persistent
user_role(name:atom, role:oneof([user,administrator])).
attach_user_db(File) :-
db_attach(File, []).
current_user_role(Name, Role) :-
with_mutex(user_db, user_role(Name, Role)).
add_user(Name, Role) :-
assert_user_role(Name, Role).
set_user_role(Name, Role) :-
user_role(Name, Role), !.
set_user_role(Name, Role) :-
with_mutex(user_db,
( retractall_user_role(Name, _),
assert_user_role(Name, Role))).
persistent +Spec
Declare dynamic database terms. Declarations appear in a directive and have the following
format:
:- persistent
<callable>,
<callable>,
...
name:type
db attach(:File, +Options)
Use File as persistent database for the calling module. The calling module must defined
persistent/1 to declare the database terms. Defined options:
sync(+Sync)
One of close (close journal after write), flush (default, flush journal after write) or
none (handle as fully buffered stream).
db detach [det]
Detach persistency from the calling module and delete all persistent clauses from the Prolog
database. Note that the file is not affected. After this operation another file may be attached,
providing it satisfies the same persistency declaration.
db sync(:What)
Synchronise database with the associated file. What is one of:
reload
Database is reloaded from file if the file was modified since loaded.
update
As reload, but use incremental loading if possible. This allows for two processes to
examine the same database file, where one writes the database and the other periodycally
calls db_sync(update) to follow the modified data.
gc
Database was re-written, deleting all retractall statements. This is the same as gc(50).
gc(Percentage)
GC DB if the number of deleted terms is the given percentage of the total number of
terms.
close
Database stream was closed
detach
Remove all registered persistency for the calling module
nop
No-operation performed
With unbound What, db sync/1 reloads the database if it was modified on disk, gc it if it is
dirty and close it if it is opened.
db sync all(+What)
Sync all registered databases.
This module is part of pio.pl, dealing with pure input: processing input streams from the
outside world using pure predicates, notably grammar rules (DCG). Using pure predicates makes
non-deterministic processing of input much simpler.
Pure input uses attributed variables to read input from the external source into a list on de-
mand. The overhead of lazy reading is more than compensated for by using block reads based on
read pending codes/3.
Ulrich Neumerkel came up with the idea to use coroutining for creating a lazy list. His implemen-
tation repositioned the file to deal with re-reading that can be necessary on backtracking. The current
implementation uses destructive assignment together with more low-level attribute handling to realise
pure input on any (buffered) stream.
:- use_module(library(dcg/basics)).
file_contains(File, Pattern) :-
phrase_from_file(match(Pattern), File).
match(Pattern) -->
string(_),
string(Pattern),
remainder(_).
This can be called as (note that the pattern must be a string (code list)):
syntax error(+Error) //
Throw the syntax error Error at the current location of the input. This predicate is designed to
be called from the handler of phrase from file/3.
See also lazy list character count//1 only provides the character count.
An integer
A term end of file-Count
See also lazy list location//1 provides full details of the location for error reporting.
Different Prolog implementations can be seen as concurrent development branches of the Prolog
language. Different sets of supported options pose a serious portability issue. Using an option O that
establishes the desired behaviour on system A leads (on most systems) to an error or system B. Porting
may require several actions:
Drop O (if the option is not vital, such as the layout options to write term/3)
Replace O by O2 (i.e., a differently named option doing the same)
Something else (cannot be ported; requires a totally different approach, etc.)
Predicates that process options are particularly a problem when writing a compatibility layer to
run programs developed for System A on System B because complete emulation is often hard, may
cause a serious slowdown and is often not needed because the application-to-be-ported only uses
options that are shared by all target Prolog implementations. Unfortunately, the consequences of a
partial emulation cannot be assessed by tools.
some_pred(..., Options) :-
pred1(..., Options),
pred2(..., Options).
As stated before, options provide a readable alternative to high-arity predicates and offer a robust
mechanism to evolve the API, but at the cost of some runtime overhead and weaker consistency
checking, both at compiletime and runtime. From our experience, the environment approach is
productive, but the consequence is that mistyped options are silently ignored. The option infrastructure
described in this section tries to remedy these problems.
Options as types
An obvious approach to deal with options is to define the different possible option values as a type and
type the argument that processes the option as list(<option type>), as illustrated below. Considering
options as types fully covers the case where we consider options as additional parameters.
There is no consensus about types in the Prolog world, neither about what types should look
like, nor whether or not they are desirable. It is not likely that this debate will be resolved
shortly.
Considering options as types does not support the environment view, which we consider the
most productive.
Even when using types, we need reflective access to what options are provided in order to be
able to write compile or runtime conditional code.
Below is an example that processes the option header(boolean) and passes all options to
open/4:
:- predicate_options(write_xml_file/3, 3,
[ header(boolean),
pass_to(open/4, 4)
]).
This predicate may only be used as a directive and is processed by expand term/2. Option
processing can be specified at runtime using assert predicate options/3, which is
intended to support program analysis.
The predicates below realise the support for compile and runtime checking for supported options.
?- current_predicate_option(open/4, 4, type(text)).
true.
This predicate is intended to support conditional compilation using if/1 ... endif/0. The
predicate current predicate options/3 can be used to access the full capabilities of a
predicate.
check predicate option(:PI, +Arg, +Option) [det]
Verify predicate options at runtime. Similar to current predicate option/3, but in-
tended to support runtime checking.
Errors
- existence_error(option, OptionName) if the option is not supported by PI.
- type_error(Type, Value) if the option is supported but the value does not match the
option type. See must be/2.
The predicates below can be used in a development environment to inform the user about sup-
ported options. PceEmacs uses this for colouring option names and values.
current option arg(:PI, ?Arg) [nondet]
True when Arg of PI processes predicate options. Which options are processed can be accessed
using current predicate option/3.
current predicate options(:PI, ?Arg, ?Options) [nondet]
True when Options is the current active option declaration for PI on Arg. See
predicate options/3 for the argument descriptions. If PI is ground and refers to
an undefined predicate, the autoloader is used to obtain a definition of the predicate.
The library can execute a complete check of your program using
check predicate options/0:
check predicate options [det]
Analyse loaded program for erroneous options. This predicate decompiles the current program
and searches for calls to predicates that process options. For each option list, it validates
whether the provided options are supported and validates the argument type. This predicate
performs partial dataflow analysis to track option-lists inside a clause.
See also derive predicate options/0 can be used to derive declarations for
predicates that pass options. This predicate should normally be called before
check predicate options/0.
The library offers predicates that may be used to create declarations for your application. These
predicates are designed to cooperate with the module system.
derive predicate options [det]
Derive new predicate option declarations. This predicate analyses the loaded program to find
clauses that process options using one of the predicates from library(option) or passes
options to other predicates that are known to process options. The process is repeated until no
new declarations are retrieved.
The library(prolog_pack) provides the SWI-Prolog package manager. This library lets
you inspect installed packages, install packages, remove packages, etc. It is complemented by the
built-in attach packs/0 that makes installed packages available as libaries.
pack info(+Pack)
Print more detailed information about Pack.
Installation status
p: package, not installed
i: installed package; up-to-date with public version
U: installed package; can be upgraded
A: installed package; newer than publically available
See also pack list installed/0 to list installed packages without contacting the server.
After resolving the type of package, pack install/2 is used to do the actual installation.
url(+URL)
Source for downloading the package
package directory(+Dir)
Directory into which to install the package
interactive(+Boolean)
Use default answer without asking the user if there is a default action.
silent(+Boolean)
If true (default false), suppress informational progress messages.
upgrade(+Boolean)
If true (default false), upgrade package if it is already installed.
git(+Boolean)
If true (default false unless URL ends with =.git=), assume the URL is a GIT reposi-
tory.
prolog_pack:environment(USER, User) :-
getenv(USER, User).
Arguments
Name is an atom denoting a valid variable name
Value is either an atom or number representing the value of the variable.
pack upgrade(+Pack) [semidet]
Try to upgrade the package Pack.
To be done Update dependencies when updating a pack from git?
directory(Directory)
Directory into which the package is installed
version(Version)
Installed version
title(Title)
Full title of the package
author(Author)
Registered author
download(URL)
Official download URL
readme(File)
Package README file (if present)
todo(File)
Package TODO file (if present)
xref source(+Source)
Gather information on Source. If Source has already been processed and is still up-to-date
according to the file timestamp, no action is taken. This predicate must be called on a file
before information can be gathered.
xref current source(?Source)
Source has been processed.
xref clean(+Source)
Remove the information gathered for Source
xref defined(?Source, ?Callable, -How)
Callable is defined in Source. How is one of
Inspired by Haskell, SWI-Prolog support quasi quotation. Quasi quotation allows for embedding
(long) strings using the syntax of an external language (e.g., HTML, SQL) in Prolog text and syntax-
aware embedding of Prolog variables in this syntax. At the same time, quasi quotation provides an
alternative to represent long strings and atoms in Prolog.
The basic form of a quasi quotation is defined below. Here, Syntax is an arbitrary Prolog term
that must parse into a callable (atom or compound) term and Quotation is an arbitrary sequence of
characters, not including the sequence |}. If this sequence needs to be embedded, it must be escaped
according to the rules of the target language or the quoter must provide an escaping mechanism.
{|Syntax||Quotation|}
While reading a Prolog term, and if the Prolog flag quasi_quotes is set to true (which is the
case if this library is loaded), the parser collects quasi quotations. After reading the final full stop, the
parser makes the call below. Here, SyntaxName is the functor name of Syntax above and SyntaxArgs
is a list holding the arguments, i.e., Syntax =.. [SyntaxName|SyntaxArgs]. Splitting the
syntax into its name and arguments is done to make the quasi quotation parser a predicate with a
consistent arity 4, regardless of the number of additional arguments.
SyntaxName is the principal functor of the quasi quotation syntax. This must be declared using
quasi quotation syntax/1 and there must be a predicate SyntaxName/4.
Content is an opaque term that carries the content of the quasi quoted material and position
information about the source code. It is passed to with quasi quote input/3.
SyntaxArgs carries the additional arguments of the Syntax. These are commonly used to make
the parameter passing between the clause and the quasi quotation explicit. For example:
...,
{|html(Name, Address)||
<tr><td>Name<td>Address</tr>
|}
VariableNames is the complete variable dictionary of the clause as it is made available throug
read term/3 with the option variable_names. It is a list of terms Name = Var.
Result is a variable that must be unified to resulting term. Typically, this term is structured Pro-
log tree that carries a (partial) representation of the abstract syntax tree with embedded variables
that pass the Prolog parameters. This term is normally either passed to a predicate that serializes
the abstract syntax tree, or a predicate that processes the result in Prolog. For example, HTML is
commonly embedded for writing HTML documents (see library(http/html_write)).
Examples of languages that may be embedded for processing in Prolog are SPARQL, RuleML
or regular expressions.
Its initial position represents the position of the start of the quoted material.
It is a text stream, using utf8 encoding.
It allows for repositioning
It will be closed after Goal completes.
Arguments
Goal is executed as once(Goal). Goal must succeed. Failure or ex-
ceptions from Goal are interpreted as syntax errors.
See also phrase from quasi quotation/2 can be used to process a quotation using a gram-
mar.
See also with quasi quotation input/3 for processing quotations from stream.
This library is derived from the DEC10 library random. Later, the core random generator was
moved to C. The current version uses the SWI-Prolog arithmetic functions to realise this library.
These functions are based on the GMP library.
random(-R:float) [det]
Binds R to a new random float in the open interval (0.0,1.0).
See also
- setrand/1, getrand/1 may be used to fetch/set the state.
- In SWI-Prolog, random/1 is implemented by the function random float/0.
setrand(+State) [det]
getrand(-State) [det]
Query/set the state of the random generator. This is intended for restarting the generator
at a known state only. The predicate setrand/1 accepts an opaque term returned by
getrand/1. This term may be asserted, written and read. The application may not make
other assumptions about this term.
For compatibility reasons with older versions of this library, setrand/1 also accepts a term
rand(A,B,C), where A, B and C are integers in the range 1..30,000. This argument is used
to seed the random generator. Deprecated.
maybe [semidet]
Succeed/fail with equal probability (variant of maybe/1).
maybe(+P) [semidet]
Succeed with probability P, fail with probability 1-P
?- randset(5, 5, S).
S = [1, 2, 3, 4, 5]. (always)
?- randset(5, 20, S).
S = [2, 7, 10, 19, 20].
randseq(K, N, List) :-
randset(K, N, Set),
random_permutation(Set, List).
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).
...,
default_point(Point),
point_x(Point, X),
set_x_of_point(10, Point, Point1),
make_point([y(20)], YPoint),
The principal functor and arity of the term used defines the name and arity of the compound used as
records. Each argument is described using a term of the format below.
hnamei[:htypei][=hdefaulti]
In this definition, hnamei is an atom defining the name of the argument, htypei is an optional type
specification as defined by must be/2 from library error, and hdefaulti is the default initial value.
The htypei defaults to any. If no default value is specified the default is an unbound variable.
A record declaration creates a set of predicates through term-expansion. We describe these predi-
cates below. In this description, hconstructori refers to the name of the record (point in the example
above) and hnamei to the name of an argument (field).
default hconstructori(-Record)
Create a new record where all fields have their default values. This is the same as
make hconstructori([], Record).
record(+Spec)
The construct :- record Spec, ... is used to define access to named fields in a com-
pound. It is subject to term-expansion (see expand term/2) and cannot be called as a
predicate. See section A.30 for details.
provides a more complete coverage of the Windows registry API. Please consult the sources in pl/
src/win32/foreign/plregtry.c for further details.
In all these predicates, Path refers to a / separated path into the registry. This is not an atom
containing /-characters as used for filenames, but a term using the functor //2. Windows defines the
following roots for the registry: classes root, current user, local machine and users.
registry get key(+Path, -Value)
Get the principal (default) value associated to this key. Fails silently if the key does not exist.
registry get key(+Path, +Name, -Value)
Get a named value associated to this key.
registry set key(+Path, +Value)
Set the principal (default) value of this key. Creates (a path to) the key if it does not already
exist.
registry set key(+Path, +Name, +Value)
Associate a named value to this key. Creates (a path to) the key if it does not already exist.
registry delete key(+Path)
Delete the indicated key.
shell register file type(+Ext, +Type, +Name, +OpenAction)
Register a file-type. Ext is the extension to associate. Type is the type name, often something
like prolog.type. Name is the name visible in the Windows file-type browser. Finally,
OpenAction defines the action to execute when a file with this extension is opened in the
Windows explorer.
shell register dde(+Type, +Action, +Service, +Topic, +Command, +IfNotRunning)
Associate DDE actions to a type. Type is the same type as used for the 2nd argument of
shell register file type/4, Action is the action to perform, Service and Topic
specify the DDE topic to address, and Command is the command to execute on this topic.
Finally, IfNotRunning defines the command to execute if the required DDE server is not
present.
shell register prolog(+Ext)
Default registration of SWI-Prolog, which is invoked as part of the initialisation process on
Windows systems. As the source also includes the above predicates, it is given as an example:
shell_register_prolog(Ext) :-
current_prolog_flag(argv, [Me|_]),
atomic_list_concat([", Me, " "%1"], OpenCommand),
shell_register_file_type(
Ext, prolog.type, Prolog Source, OpenCommand),
shell_register_dde(
prolog.type, consult,
prolog, control, consult(%1), Me),
shell_register_dde(
prolog.type, edit,
prolog, control, edit(%1), Me).
A.32.1 Introduction
A linear programming problem or simply linear program (LP) consists of:
The goal is to assign values to the variables so as to maximize (or minimize) the value of the
objective function while satisfying all constraints.
Many optimization problems can be modeled in this way. As one basic example, consider a
knapsack with fixed capacity C, and a number of items with sizes s(i) and values v(i). The goal
is to put as many items as possible in the knapsack (not exceeding its capacity) while maximizing the
sum of their values.
As another example, suppose you are given a set of coins with certain values, and you are to find
the minimum number of coins such that their values sum up to a fixed amount. Instances of these
problems are solved below.
Solving an LP or integer linear program (ILP) with this library typically comprises 4 stages:
3. maximize/3 or minimize/3 are used to obtain a solved state that represents an optimum
solution
4. variable value/3 and objective/2 are used on the solved state to obtain variable
values and the objective function at the optimum.
gen state(-State)
Generates an initial state corresponding to an empty linear program.
A.32.4 Examples
We include a few examples for solving LPs with this library.
Example 1
This is the radiation therapy example, taken from Introduction to Operations Research by Hillier
and Lieberman.
Prolog DCG notation is used to implicitly thread the state through posting the constraints:
:- use_module(library(simplex)).
radiation(S) :-
gen_state(S0),
post_constraints(S0, S1),
minimize([0.4*x1, 0.5*x2], S1, S).
post_constraints -->
constraint([0.3*x1, 0.1*x2] =< 2.7),
constraint([0.5*x1, 0.5*x2] = 6),
constraint([0.6*x1, 0.4*x2] >= 6),
constraint([x1] >= 0),
constraint([x2] >= 0).
An example query:
Example 2
Here is an instance of the knapsack problem described above, where C = 8, and we have two types
of items: One item with value 7 and size 6, and 2 items each having size 4 and value 4. We introduce
two variables, x(1) and x(2) that denote how many items to take of each type.
:- use_module(library(simplex)).
knapsack(S) :-
knapsack_constraints(S0),
maximize([7*x(1), 4*x(2)], S0, S).
knapsack_constraints(S) :-
gen_state(S0),
constraint([6*x(1), 4*x(2)] =< 8, S0, S1),
constraint([x(1)] =< 1, S1, S2),
constraint([x(2)] =< 2, S2, S).
That is, we are to take the one item of the first type, and half of one of the items of the other type
to maximize the total value of items in the knapsack.
If items can not be split, integrality constraints have to be imposed:
knapsack_integral(S) :-
knapsack_constraints(S0),
constraint(integral(x(1)), S0, S1),
constraint(integral(x(2)), S1, S2),
maximize([7*x(1), 4*x(2)], S2, S).
X1 = 0
X2 = 2
That is, we are to take only the two items of the second type. Notice in particular that always
choosing the remaining item with best performance (ratio of value to size) that still fits in the knapsack
does not necessarily yield an optimal solution in the presence of integrality constraints.
Example 3
We are given:
The task is to find a minimal number of these coins that amount to 111 units in total. We introduce
variables c(1), c(5) and c(20) denoting how many coins to take of the respective type:
:- use_module(library(simplex)).
coins(S) :-
gen_state(S0),
coins(S0, S).
coins -->
constraint([c(1), 5*c(5), 20*c(20)] = 111),
constraint([c(1)] =< 3),
constraint([c(5)] =< 20),
constraint([c(20)] =< 10),
constraint([c(1)] >= 0),
constraint([c(5)] >= 0),
constraint([c(20)] >= 0),
constraint(integral(c(1))),
constraint(integral(c(5))),
constraint(integral(c(20))),
minimize([c(1), c(5), c(20)]).
An example query:
C1 = 1,
C5 = 2,
C20 = 5.
The meta predicates of this library modify the sequence of solutions of a goal. The modifications
and the predicate names are based on the classical database operations DISTINCT, LIMIT, OFFSET,
ORDER BY and GROUP BY.
These predicates were introduced in the context of the SWISH Prolog browser-based shell, which
can represent the solutions to a predicate as a table. Notably wrapping a goal in distinct/1 avoids
duplicates in the result table and using order by/2 produces a nicely ordered table.
However, the predicates from this library can also be used to stay longer within the clean paradigm
where non-deterministic predicates are composed from simpler non-deterministic predicates by means
of conjunction and disjunction. While evaluating a conjunction, we might want to eliminate duplicates
of the first part of the conjunction. Below we give both the classical solution for solving variations of
(a(X), b(X)) and the ones using this library side-by-side.
Avoid duplicates
setof(X, of earlier
a(X), steps
Xs), distinct(a(X)),
member(X, Xs), b(X)
b(X).
Note that the distinct/1 based solution returns the first result of distinct(a(X)) im-
mediately after a/1 produces a result, while the setof/3 based solution will first compute
all results of a/1.
Here we see power of composing primitives from this library and staying within the paradigm
of pure non-deterministic relational predicates.
distinct(:Goal)
distinct(?Witness, :Goal)
True if Goal is true and no previous solution of Goal bound Witness to the same value. As
previous answers need to be copied, equivalence testing is based on term variance (=@=/2).
The variant distinct/1 is equivalent to distinct(Goal,Goal).
If the answers are ground terms, the predicate behaves as the code below, but answers are
returned as soon as they become available rather than first computing the complete answer set.
distinct(Goal) :-
findall(Goal, Goal, List),
list_to_set(List, Set),
member(Goal, Set).
limit(+Count, :Goal)
Limit the number of solutions. True if Goal is true, returning at most Count solutions. Solutions
are returned as soon as they become available.
offset(+Count, :Goal)
Ignore the first Count solutions. True if Goal is true and produces more than Count solutions.
This predicate computes and ignores the first Count solutions.
asc(Term)
Order solution according to ascending Term
desc(Term)
Order solution according to descending Term
1. Re-evaluation of a tabled predicate is avoided by memoizing the answers. This can realise huge
performance enhancements as illustrated in section A.34. It also comes with two downsides: the
memoized answers are not automatically updated or invalidated if the world (set of predicates
on which the answers depend) changes and the answer tables must be stored (in memory).
2. Left recursion, a goal calling a variant of itself recursively and thus looping under the normal
Prolog SLD resolution is avoided by suspending the variant call and resuming it with answers
from the table. This is illustrated in section A.34.
Tabling is particularly suited to simplify inference over a highly entangled set of predicates that
express axioms and rules in a static (not changing) world. When using SLD resolution for such
problems, it is hard to ensure termination and avoid frequent recomputation of intermediate results. A
solution is to use Datalog style bottom-up evaluation, i.e., applying rules on the axioms and derived
facts until a fixed point is reached. However, bottom-up evaluation typically derives many facts that
are never used. Tabling provides a goal oriented resolution strategy for such problems and is enabled
simply by adding a table/1 directive to the program.
fib(0, 1) :- !.
fib(1, 1) :- !.
fib(N, F) :-
N > 1,
N1 is N-1,
N2 is N-2,
fib(N1, F1),
fib(N2, F2),
F is F1+F2.
The complexity of executing this using SLD resolution however is 2N and thus becomes prohibitively
slow rather quickly, e.g., the execution time for N = 30 is already 0.4 seconds. Using tabling,
fib(N,F) for each value of N is computed only once and the algorithm becomes linear. Tabling
effectively inverts the execution order for this case: it suspends the final addition (F is F1+F2) until
the two preceeding Fibonacci numbers have been added to the answer tables. Thus, we can reduce
the complexity from the show-stopping 2N to linear by adding a tabling directive and otherwise not
changing the algorithm. The code becomes:
:- use_module(library(tabling)).
:- table fib/2.
fib(0, 1) :- !.
fib(1, 1) :- !.
fib(N, F) :-
N > 1,
N1 is N-1,
N2 is N-2,
fib(N1, F1),
fib(N2, F2),
F is F1+F2.
The price that we pay is that a table fib(I,F) is created for each I in 0..N . The execution time for
N = 30 is now 1 millisecond and computing the Fibonacci number for N = 1000 is doable (output
edited for readability).
1 ?- time(fib(1000, X)).
% 52,991 inferences, 0.013 CPU in 0.013 seconds
X = 70330367711422815821835254877183549770181269836358
73274260490508715453711819693357974224949456261173
34877504492417659910881863632654502236471060120533
74121273867339111198139373125598767690091902245245
323403501.
In the case of Fibonacci numbers we can still rather easily achieve linear complexity using program
transformation, where we use bottom-up instead of top-down evaluation, i.e., we compute fib(N,F)
for growing N , where we pass the last two Fibonacci numbers to the next iteration. Not having to
create the tables and not having to suspend and resume goals makes this implementatio about 25 times
faster than the tabled one. However, even in this simple case the transformation is not obvious and it
is far more difficult to recognise the algorithm as an implementation of Fibonacci numbers.
fib(0, 1) :- !.
fib(1, 1) :- !.
fib(N, F) :-
fib(1,1,1,N,F).
% :- use_module(library(tabling)).
% :- table connection/2.
connection(X, Y) :-
connection(X, Z),
connection(Z, Y).
connection(X, Y) :-
connection(Y, X).
connection(Amsterdam, Schiphol).
connection(Amsterdam, Haarlem).
connection(Schiphol, Leiden).
connection(Haarlem, Leiden).
After enabling tabling however, the above works just fine as illustrated in the session below.
Where is the magic and what is the price we paid? The magic is, again, the fact that new goals
to the tabled predicate suspend. So, all recursive goals are suspended. Eventually, a table for
connection(Amsterdam, X) is created with the two direct connections from Amsterdam. Now, it
resumes the first clause using the tabled solutions, continuing the last connection/2 subgoal with
connection(Schiphol, X) and connection(Haarlem, X). These two go through the same pro-
cess, creating new suspended recursive calls and creating tables for the connections from Schiphol and
Haarlem. Eventually, we end up with a set of tables for each call variant that is involved in computing
the transitive closure of the network starting in Amsterdam. However, if the Japanese rail network
would have been in our data as well, we would not have produced tables for that.
1 ?- connection(Amsterdam, X).
X = Haarlem ;
X = Schiphol ;
X = Amsterdam ;
X = Leiden.
Again, the fact that a simple table/1 directive turns the pure logical specification into a fairly
efficient algorithm is a clear advantage. Without tabling the program needs to be stratified, introducing
a base layer with the raw connections, a second layer that introduces the commutative property of a
railway (if you can travel from A to B you can also travel from B to A and a final layer that realises
transitivity (if you can travel from A to B and from B to C you can also travel from A to C). The
third and final layer must keep track which cities you have already visited to avoid traveling in circles.
The transformed program however uses little memory (the list of already visited cities and the still
open choices) and does not need to deal with maintaining consistency between the tables and ground
facts.
The SWI-Prolog implementation uses Delimited continuations (see section 4.10 to realise sus-
pension of variant calls. The initial version was written by Benoit Desouter and described in
[Desouter et al., 2015]. We moved the main data structures required for tabling, the answer tables
(see section 4.14.4) and the worklist to SWI-Prologs C core.
The table/1 directive causes the creation of a wrapper calling the renamed original predicate.
For example, the program in section A.34 is translated into the following program. We give this
information to improve your understanding of the current tabling implementation. Future versions are
likely to use a more low-level translation that is not based on wrappers.
connection(A, B) :-
start_tabling(user:connection(A, B),
connection tabled(A, B)).
connection tabled(X, Y) :-
connection(X, Z),
connection(Z, Y).
connection tabled(X, Y) :-
connection(Y, X).
Status of tabling
The current implementation is merely a first prototype. It needs several enhancements before we
can consider it a serious competitor to Prolog systems with mature tabling such as XSB, YAP and
B-Prolog. In particular,
Creating many CPU intensive threads often leads to a slow-down rather than a speedup.
Creating many memory intensive threads may exhaust resources
Tasks that require little CPU and memory but take long waiting for external resources can run
many threads.
Using this library, one can define a pool for each set of tasks with comparable characteristics
and create threads in this pool. Unlike the worker-pool model, threads are not started immediately.
Depending on the design, both approaches can be attractive.
The library is implemented by means of a manager thread with the fixed thread id
__thread_pool_manager. All state is maintained in this manager thread, which receives and
processes requests to create and destroy pools, create threads in a pool and handle messages from
terminated threads. Thread pools are not saved in a saved state and must therefore be recreated using
the initialization/1 directive or otherwise during startup of the application.
backlog(+MaxBackLog)
Maximum number of requests that can be suspended. Default is infinite. Otherwise
it must be a non-negative integer. Using backlog(0) will never delay thread creation
for this pool.
The pooling mechanism does not interact with the detached state of a thread. Threads can
be created both detached and normal and must be joined using thread join/2 if they are
not detached.
options(Options)
Thread creation options for this pool
free(Size)
Number of free slots on this pool
size(Size)
Total number of slots on this pool
members(ListOfIDs)
ListOfIDs is the list or threads running in this pool
running(Running)
Number of running threads in this pool
backlog(Size)
Number of delayed thread creations on this pool
wait(+Boolean)
If true (default) and the pool is full, wait until a member of the pool completes. If
false, throw a resource error.
Errors
- resource_error(threads_in_pool(Pool)) is raised if wait is false or the back-
log limit has been reached.
- existence_error(thread_pool, Pool) if Pool does not exist.
:- multifile thread_pool:create_pool/1.
thread_pool:create_pool(media) :-
thread_pool_create(media, 20, []).
Implementation and documentation are copied from YAP 5.0.1. The ugraph library is
based on code originally written by Richard OKeefe. The code was then extended to be
compatible with the SICStus Prolog ugraphs library. Code and documentation have been
cleaned and style has been changed to be more in line with the rest of SWI-Prolog.
The ugraphs library was originally released in the public domain. The YAP version is
covered by the Perl Artistic license, version 2.0. This code is dual-licensed under the
modified GPL as used for all SWI-Prolog libraries or the Perl Artistic license, version
2.0.
The routines assume directed graphs; undirected graphs may be implemented by using two edges.
Originally graphs were represented in two formats. The SICStus library and this version of
ugraphs.pl only use the S-representation. 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. Each vertex appears in the S-representation, even if it has no neighbors.
?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5], L).
L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[]]
In this case all vertices are defined implicitly. The next example shows three unconnected
vertices:
?- 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-[]] ?
vertices(+Graph, -Vertices)
Unify Vertices with all vertices appearing in Graph. Example:
?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
L = [1, 2, 3, 4, 5]
edges(+Graph, -Edges)
Unify Edges with all edges appearing in Graph. Example:
?- edges([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
L = [1-3, 1-5, 2-4, 4-5]
?- 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-[]]
?- 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-[]]
?- 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-[]]
?- transpose_ugraph([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-[]]
?- neighbours(4,[1-[3,5],2-[4],3-[],
4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
NL = [1,2,7,5]
complement(+Graph, -NewGraph)
Unify NewGraph with the graph complementary to Graph. 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]]
?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
L = [1-[4], 2-[1,2,4], 3-[]]
?- ugraph_union([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
L = [1-[2], 2-[3,4], 3-[1,2,4]]
?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L).
L = [1-[2,3,4,5,6], 2-[4,5,6], 4-[6]]
?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V).
V = [1, 3, 5]
This library deals with the analysis and construction of a URL, Universal Resource Locator. URL
is the basis for communicating locations of resources (data) on the web. A URL consists of a protocol
identifier (e.g. HTTP, FTP, and a protocol-specific syntax further defining the location. URLs are
standardized in RFC-1738.
The implementation in this library covers only a small portion of the defined protocols. Though the
initial implementation followed RFC-1738 strictly, the current is more relaxed to deal with frequent
violations of the standard encountered in practical use.
is absolute url(+URL)
True if URL is an absolute URL. That is, a URL that starts with a protocol identifier.
Arguments
Location Atom or list of character codes.
protocol(Protocol)
The used protocol. This is, after the optional url:, an identifier separated from the
remainder of the URL using :. parse url/2 assumes the http protocol if no protocol
is specified and the URL can be parsed as a valid HTTP url. In addition to the RFC-1738
specified protocols, the file protocol is supported as well.
host(Host)
Host-name or IP-address on which the resource is located. Supported by all network-based
protocols.
port(Port)
Integer port-number to access on the \arg{Host}. This only appears if the port is explic-
itly specified in the URL. Implicit default ports (e.g., 80 for HTTP) do not appear in the
part-list.
path(Path)
(File-) path addressed by the URL. This is supported for the ftp, http and file
protocols. If no path appears, the library generates the path /.
search(ListOfNameValue)
Search-specification of HTTP URL. This is the part after the ?, normally used to transfer
data from HTML forms that use the GET protocol. In the URL it consists of a www-form-
encoded list of Name=Value pairs. This is mapped to a list of Prolog Name=Value terms
with decoded names and values.
fragment(Fragment)
Fragment specification of HTTP URL. This is the part after the # character.
?- parse_url(http://www.xyz.org/hello?msg=Hello+World%21#x,
P).
P = [ protocol(http),
host(www.xyz.org),
fragment(x),
search([ msg = Hello World!
]),
path(/hello)
]
To be done Having a global flag is highly inconvenient, but a work-around for old sites using ISO
Latin 1 encoding.
To be done Current implementation does not deal with paths that need special encoding.
This library provides the inverse functionality of the built-in numbervars/3. Note that this
library suffers from the known issues that $VAR(X) is a normal Prolog term and, -unlike the built-in
numbervars-, the inverse predicates do not process cyclic terms. The following predicate is true for
any acyclic term that contains no $VAR(X), integer(X) terms and no constraint variables:
always_true(X) :-
copy_term(X, X2),
numbervars(X),
varnumbers(X, Copy),
Copy =@= X2.
numbervars(+Term) [det]
Number variables in Term using $VAR(N). Equivalent to numbervars(Term, 0, _).
See also numbervars/3, varnumbers/3, read term/3 using the variable_names op-
tion.
Prolog realizes high-order programming with meta-calling. The core predicate of this is call/1,
which simply calls its argument. This can be used to define higher-order predicates such as
ignore/1 or forall/2. The call/N construct calls a closure with N-1 additional arguments.
This is used to define higher-order predicates such as the maplist/N family or foldl/N.
The problem with higher order predicates based on call/N is that the additional arguments
are always added to the end of the closures argument list. This often requires defining triv-
ial helper predicates to get the argument order right. For example, if you want to add a com-
mon postfix to a list of atoms you need to apply atom_concat(In,Postfix,Out), but
maplist(x(PostFix),ListIn,ListOut) calls x(PostFix,In,Out). This is where this
library comes in, which allows us to write
The {...} specifies which variables are shared between the lambda and the context. This
allows us to write the code below. Without the {PostFix} a free variable would be passed to
atom concat/3.
This introduces the second application area of lambda expressions: the ability to stop binding
variables in the context. This features shines when combined with bagof/3 or setof/3 where
you normally have to specify the the variables in whose binding you are not interested using the
VarGoal construct (marking Var as existential quantified). Lambdas allow doing the reverse: spec-
ify the variables in which you are interested.
Lambda expressions use the syntax below
{...}/[...]>>Goal.
The {...} optional part is used for lambda-free variables. The order of variables doesnt matter
hence the {...} set notation.
The [...] optional part lists lambda parameters. Here order of variables matters hence the list
notation.
As / and >> are standard infix operators, no new operators are added by this library. An advantage
of this syntax is that we can simply unify a lambda expression with Free/Parameters>>Lambda to
access each of its components. Spaces in the lambda expression are not a problem although the goal
may need to be written between ()s. Goals that are qualified by a module prefix also need to be
wrapped inside parentheses.
Combined with library(apply_macros), library(yall) allows writing one-liners for
many list operations that have the same performance as hand written code.
The module name, yall, stands for Yet Another Lambda Library.
This module implements Logtalks lambda expressions syntax. The development of this module
was sponsored by Kyndi, Inc.
The first length(Parameters) arguments from A1, ... are unified with (a copy of)
Parameters, which may share them with variables in Lambda.
Possible excess arguments are passed by position.
Arguments
Parameters is either a plain list of parameters or a term {Free}/List. Free
represents variables that are shared between the context and the
Lambda term. This is needed for compiling Lambda expressions.
+Free / :Lambda
/(+Free, :Lambda, ?A1)
/(+Free, :Lambda, ?A1, ?A2)
/(+Free, :Lambda, ?A1, ?A2, ?A3)
/(+Free, :Lambda, ?A1, ?A2, ?A3, ?A4)
/(+Free, :Lambda, ?A1, ?A2, ?A3, ?A4, ?A5)
/(+Free, :Lambda, ?A1, ?A2, ?A3, ?A4, ?A5, ?A6)
/(+Free, :Lambda, ?A1, ?A2, ?A3, ?A4, ?A5, ?A6, ?A7)
Shorthand for Free/[]>>Lambda. This is the same as applying call/N on Lambda, except
that only variables appearing in Free are bound by the call. For example
p(1,a).
p(2,b).
?- {X}/p(X,Y).
X = 1;
X = 2.
This can in particularly be combined with bagof/3 and setof/3 to select particular vari-
ables to be concerned rather than using existential quantification (/2) to exclude variables.
For example, the two calls below are equivalent.
is lambda(@Term) [semidet]
True if Term is a valid Lambda expression.
alternative
Value is unified with an integer reference to the local stack frame in which execution is
resumed if the goal associated with Frame fails. Fails if the frame has no alternative
frame.
has alternatives
Value is unified with true if Frame still is a candidate for backtracking; false other-
wise.
goal
Value is unified with the goal associated with Frame. If the definition module of the
active predicate is not the calling context, the goal is represented as hmodulei:hgoali. Do
not instantiate variables in this goal unless you know what you are doing! Note that the
returned term may contain references to the frame and should be discarded before the
frame terminates.1
1
The returned term is actually an illegal Prolog term that may hold references from the global to the local stack to
preserve the variable names.
parent goal
If Value is instantiated to a callable term, find a frame executing the predicate described
by Value and unify the arguments of Value to the goal arguments associated with the
frame. This is intended to check the current execution context. The user must ensure the
checked parent goal is not removed from the stack due to last-call optimisation and be
aware of the slow operation on deeply nested calls.
predicate indicator
Similar to goal, but only returning the [hmodulei:]hnamei/harityi term describing the
term, not the actual arguments. It avoids creating an illegal term as goal and is used by
the library prolog stack.
clause
Value is unified with a reference to the currently running clause. Fails if the current
goal is associated with a foreign (C) defined predicate. See also nth clause/3 and
clause property/2.
level
Value is unified with the recursion level of Frame. The top level frame is at level 0.
parent
Value is unified with an integer reference to the parent local stack frame of Frame. Fails
if Frame is the top frame.
context module
Value is unified with the name of the context module of the environment.
top
Value is unified with true if Frame is the top Prolog goal from a recursive call back
from the foreign language; false otherwise.
hidden
Value is unified with true if the frame is hidden from the user, either because a parent
has the hide-childs attribute (all system predicates), or the system has no trace-me
attribute.
skipped
Value is true if this frame was skipped in the debugger.
pc
Value is unified with the program pointer saved on behalf of the parent goal if the parent
goal is not owned by a foreign predicate or belongs to a compound meta-call (e.g.,
call((a,b))).
argument(N)
Value is unified with the N-th slot of the frame. Argument 1 is the first argument of the
goal. Arguments above the arity refer to local variables. Fails silently if N is out of range.
parent
Requests a reference to the first older choice point.
frame
Requests a reference to the frame to which the choice point refers.
type
Requests the type. Defined values are clause (the goal has alternative clauses),
foreign (non-deterministic foreign predicate), jump (clause internal choice point),
top (first dummy choice point), catch (catch/3 to allow for undo), debug (help the
debugger), or none (has been deleted).
This predicate is used for the graphical debugger to show the choice point stack.
deterministic(-Boolean)
Unifies its argument with true if no choice point exists that is more recent than the entry of the
clause in which it appears. There are few realistic situations for using this predicate. It is used
by the prolog/0 top level to check whether Prolog should prompt the user for alternatives.
Similar results can be achieved in a more portable fashion using call cleanup/2.
call
Normal entry through the call port of the 4-port debugger.
redo(PC)
Normal entry through the redo port of the 4-port debugger. The redo port signals resum-
ing a predicate to generate alternative solutions. If PC is 0 (zero), clause indexing has
found another clause that will be tried next. Otherwise, PC is the program counter in the
current clause where execution continues. This implies we are dealing with an in-clause
choice point left by, e.g., ;/2. Note that non-determinism in foreign predicates are also
handled using an in-clause choice point.
unify
The unify port represents the neck instruction, signalling the end of the head-matching
process. This port is normally invisible. See leash/1 and visible/1.
exit
The exit port signals the goal is proved. It is possible for the goal to have alternatives. See
prolog frame attribute/3 to examine the goal stack.
fail
The fail port signals final failure of the goal.
exception(Except)
An exception is raised and still pending. This port is activated on each parent frame of the
frame generating the exception until the exception is caught or the user restarts normal
computation using retry. Except is the pending exception term.
break(PC)
A break instruction is executed. PC is program counter. This port is used by the graphi-
cal debugger.
cut call(PC)
A cut is encountered at PC. This port is used by the graphical debugger to visualise the
effect of the cut.
cut exit(PC)
A cut has been executed. See cut call(PC) for more information.
Frame is a reference to the current local stack frame, which can be examined using
prolog frame attribute/3. Choice is a reference to the last choice point and can be
examined using prolog choice attribute/3. Action must be unified with a term that
specifies how execution must continue. The following actions are defined:
abort
Abort execution. See abort/0.
continue
Continue (i.e., creep in the command line debugger).
fail
Make the current goal fail.
ignore
Step over the current goal without executing it.
nodebug
Continue execution in normal nodebugging mode. See nodebug/0.
retry
Retry the current frame.
retry(Frame)
Retry the given frame. This must be a parent of the current frame.
skip
Skip over the current goal (i.e., skip in the command line debugger).
up
Skip to the parent goal (i.e., up in the command line debugger).
Together with the predicates described in section 4.39 and the other predicates of this chapter,
this predicate enables the Prolog user to define a complete new debugger in Prolog. Besides
this, it enables the Prolog programmer to monitor the execution of a program. The example
below records all goals trapped by the tracer in the database.
To trace the execution of go this way the following query should be given:
call(Goal)
The instruction will call Goal. This is generated for nearly all instructions. Note that
Goal is semantically equivalent to the compiled body term, but might differ syntactically.
This is notably the case when arithmetic expressions are compiled in optimized mode
(see optimise). In particular, the arguments of arithmetic expressions have already
been evaluated. Thus, A is 3*B, where B equals 3 results in a term call(A is 9) if
the clause was compiled with optimization enabled.
!
The instruction will call the cut. Because the semantics of metacalling the cut differs
from executing the cut in its original context we do not wrap the cut in call/1.
:-
The breakpoint is on the neck instruction, i.e., after performing the head unifications.
exit
The breakpoint is on the exit instruction, i.e., at the end of the clause. Note that the exit
instruction may not be reached due to last-call optimisation.
unify exit
The breakpoint is on the completion of an in-lined unification while the system is not
in debug mode. If the system is in debug mode, inlined unification is returned as
call(Var=Term).2
If prolog:break hook/6 succeeds, it must unify Action with a value that describes how execution
must continue. Possible values for Action are:
continue
Just continue as if no breakpoint was present.
debug
Continue in debug mode. See debug/0.
trace
Continue in trace mode. See trace/0.
call(Goal)
Execute Goal instead of the goal that would be executed. Goal is executed as call/1,
preserving (non-)determinism and exceptions.
If this hook throws an exception, the exception is propagated normally. If this hook is not
defined or fails, the default action is executed. This implies that, if the thread is in debug mode,
the tracer will be enabled (trace) and otherwise the breakpoint is ignored (continue).
This hook allows for injecting various debugging scenarios into the executable without recom-
piling. The hook can access variables of the calling context using the frame inspection predi-
cates. Here are some examples.
Create conditional breakpoints by imposing conditions before deciding the return trace.
Watch variables at a specific point in the execution. Note that binding of these variables
can be monitored using attributed variables, see section 7.1.
Dynamically add assertions on variables using assertion/1.
Wrap the Goal into a meta-call that traces progress of the Goal.
2
This hack will disappear if we find a good solution for applying D BREAK to inlined unification. Only option might
be to place the break on both the unification start and end instructions.
user:prolog_exception_hook(
error(evaluation_error(zero_divisor), _),
_, _, _) :-
trace, fail.
undefined predicate
Context is instantiated to a predicate indicator ([module]:hnamei/harityi). If the predicate
fails, Prolog will generate an existence error exception. The hook is intended
to implement alternatives to the built-in autoloader, such as autoloading code from a
database. Do not use this hook to suppress existence errors on predicates. See also
unknown and section 2.13.
undefined global variable
Context is instantiated to the name of the missing global variable. The hook must call
nb setval/2 or b setval/2 before returning with the action retry.
spy(Spec)
Hook in spy/1. If the hook succeeds spy/1 takes no further action.
nospy(Spec)
Hook in nospy/1. If the hook succeeds nospy/1 takes no further action. If spy/1 is
hooked, it is advised to place a complementary hook for nospy/1.
nospyall
Hook in nospyall/0. Should remove all spy points. This hook is called in a failure-
driven loop.
debugging
Hook in debugging/0. It can be used in two ways. It can report the status of the
additional debug points controlled by the above hooks and fail to let the system report the
others, or it succeeds, overruling the entire behaviour of debugging/0.
prolog:help hook(+Action)
Hook into help/0 and help/1. If the hook succeeds, the built-in actions are not executed.
For example, ?- help(picture). is caught by the XPCE help hook to give help on the
class picture. Defined actions are:
help
User entered plain help/0 to give default help. The default performs help(help/1),
giving help on help.
help(What)
Hook in help/1 on the topic What.
apropos(What)
Hook in apropos/1 on the topic What.
This hook is exploited by the documentation system. See stream position data/3. See
also read term/3.
The Prolog flag dialect is an unambiguous and fast way to find out which Prolog dialect
executes your program. It has the value swi for SWI-Prolog and yap on YAP.
The Prolog flag version data is bound to a term swi(Major, Minor, Patch, Extra)
The predicate expects dialect/1 allows for specifying for which Prolog system the code
was written.
The predicates exists source/1 and source exports/2 can be used to query the li-
brary content. The require/1 directive can be used to get access to predicates without know-
ing their location.
The module predicates use module/1, use module/2 have been extended with a notion
for import-except and import-as. This is particularly useful together with reexport/1
and reexport/2 to compose modules from other modules and mapping names.
Foreign code can expect SWI PROLOG when compiled for SWI-Prolog and
YAP PROLOG when compiled on YAP.
:- expects dialect(+Dialect)
This directive states that the code following the directive is written for the given Prolog Dialect.
See also dialect. The declaration holds until the end of the file in which it appears. The
current dialect is available using prolog load context/2.
The exact behaviour of this predicate is still subject to discussion. Of course, if Dialect
matches the running dialect the directive has no effect. Otherwise we check for the existence of
library(dialect/Dialect) and load it if the file is found. Currently, this file has this function-
ality:
1
http://yap.sourceforge.net/
exists source(+Spec)
Is true if Spec exists as a Prolog source. Spec uses the same conventions as load files/2.
Fails without error if Spec cannot be found.
Probably the best reason for this is that it allows to define minimal semantics required by the
application for the portability predicates. Such functionality can often be mapped efficiently to
the target dialect. Contrary, if code was written for dialect X, the defined semantics are those
of dialect X. Emulating all extreme cases and full error handling compatibility may be tedious
and result in a much slower implementation that needed. Take for example call cleanup/2.
The SICStus definition is fundamentally different from the SWI definition, but 99% of the appli-
cations just want to make calls like below to guarantee StreamIn is closed, even if process/1
misbehaves.
call_cleanup(process(StreamIn), close(In))
As a drawback, the code becomes full of my call cleanup, etc. and every potential portability
conflict needs to be abstracted. It is hard for people who have to maintain such code later to
grasp the exact semantics of the my * predicates and applications that combine multiple libraries
using this compatibility approach are likely to encounter conflicts between the portability layers.
A good start is not to use my *, but a prefix derived from the library or application name or
names that explain the intended semantics more precisely.
Another problem is that most code is initially not written with portability in mind. Instead,
ports are requested by users or arise from the desire to switch Prolog dialect. Typically, we
want to achieve compatibility with the new Prolog dialect with minimal changes, often keeping
compatibility with the original dialect(s). This problem is well known from the C/Unix world
and we advise anyone to study the philosophy of GNU autoconf, from which we will illustrate
some highlights below.
The GNU autoconf suite, known to most people as configure, was an answer to the frustrating
life of Unix/C programmers when Unix dialects were about as abundant and poorly standardised as
Prolog dialects today. Writing a portable C program can only be achieved using cpp, the C preproces-
sor. The C preprocessor performs two tasks: macro expansion and conditional compilation. Prolog
realises macro expansion through term expansion/2 and goal expansion/2. Conditional
compilation is achieved using :- if(Condition) as explained in section 4.3.1. The situation
appears similar.
The important lesson learned from GNU autoconf is that the last resort for conditional compilation
to achieve portability is to switch on the platform or dialect. Instead, GNU autoconf allows you to
write tests for specific properties of the platform. Most of these are whether or not some function or
file is available. Then there are some standard tests for difficult-to-write-portable situations and finally
there is a framework that allows you to write arbitrary C programs and check whether they can be
compiled and/or whether they show the intended behaviour. Using a separate configure program
is needed in C, as you cannot perform C compilation step or run C programs from the C preprocessor.
In most Prolog environments we do not need this distinction as the compiler is integrated into the
runtime environment and Prolog has excellent reflexion capabilities.
We must learn from the distinction to test for features instead of platform (dialect), as this makes
the platform-specific code robust for future changes of the dialect. Suppose we need compare/3 as
defined in this manual. The compare/3 predicate is not part of the ISO standard, but many systems
support it and it is not unlikely it will become ISO standard or the intended dialect will start supporting
it. GNU autoconf strongly advises to test for the availability:
:- if(\+current_predicate(_, compare(_,_,_))).
compare(<, Term1, Term2) :-
Term1 @< Term2, !.
compare(>, Term1, Term2) :-
Term1 @> Term2, !.
compare(=, Term1, Term2) :-
Term1 == Term2.
:- endif.
This code is much more robust against changes to the intended dialect and, possibly at least as impor-
tant, will provide compatibility with dialects you didnt even consider porting to right now.
In a more challenging case, the target Prolog has compare/3, but the semantics are different.
What to do? One option is to write a my compare/3 and change all occurrences in the code.
Alternatively you can rename calls using goal expansion/2 like below. This construct will not
only deal with Prolog dialects lacking compare/3 as well as those that only implement it for numeric
comparison or have changed the argument order. Of course, writing rock-solid code would require a
complete test-suite, but this example will probably cover all Prolog dialects that allow for conditional
compilation, have core ISO facilities and provide goal expansion/2, the things we claim a Prolog
dialect should have to start writing portable code for it.
:- if(\+catch(compare(<,a,b), _, fail)).
compare_standard_order(<, Term1, Term2) :-
Term1 @< Term2, !.
compare_standard_order(>, Term1, Term2) :-
Term1 @> Term2, !.
arguments
Arguments are terms that appear in a compound term. A1 and a2 are the first and second
argument of the term myterm(A1, a2).
arity
Argument count (= number of arguments) of a compound term.
assert
Add a clause to a predicate. Clauses can be added at either end of the clause-list of a predicate.
See asserta/1 and assertz/1.
atom
Textual constant. Used as name for compound terms, to represent constants or text.
backtracking
Search process used by Prolog. If a predicate offers multiple clauses to solve a goal, they are
tried one-by-one until one succeeds. If a subsequent part of the proof is not satisfied with the
resulting variable binding, it may ask for an alternative solution (= binding of the variables),
causing Prolog to reject the previously chosen clause and try the next one.
built-in [predicate]
Predicate that is part of the Prolog system. Built-in predicates cannot be redefined by the user,
unless this is overruled using redefine system predicate/1.
body
Part of a clause behind the neck operator (:-).
choice point
A choice point represents a choice in the search for a solution. Choice points are created if
multiple clauses match a query or using disjunction (;/2). On backtracking, the execution
state of the most recent choice point is restored and search continues with the next alternative
(i.e., next clause or second branch of ;/2).
clause
Sentence of a Prolog program. A clause consists of a head and body separated by the neck
operator (:-) or it is a fact. For example:
parent(X) :-
father(X, _).
compile
Process where a Prolog program is translated to a sequence of instructions. See also interpreted.
SWI-Prolog always compiles your program before executing it.
compound [term]
Also called structure. It consists of a name followed by N arguments, each of which are terms.
N is called the arity of the term.
context module
If a term is referring to a predicate in a module, the context module is used to find the target
module. The context module of a goal is the module in which the predicate is defined, unless
this predicate is module transparent, in which case the context module is inherited from the
parent goal. See also module transparent/1 and meta-predicate.
dcg
Abbreviation for Definite Clause Grammar.
det [determinism]
Short for deterministic.
determinism
How many solutions a goal can provide. Values are nondet (zero to infinite), multi (one to
infinite), det (exactly one) and semidet (zero or one).
deterministic
A predicate is deterministic if it succeeds exactly one time without leaving a choice point.
dynamic [predicate]
A dynamic predicate is a predicate to which clauses may be asserted and from which clauses
may be retracted while the program is running. See also update view.
exported [predicate]
A predicate is said to be exported from a module if it appears in the public list. This im-
plies that the predicate can be imported into another module to make it visible there. See also
use module/[1,2].
fact
Clause without a body. This is called a fact because, interpreted as logic, there is no condition
to be satisfied. The example below states john is a person.
person(john).
fail
A goal is said to haved failed if it could not be proven.
float
Computers crippled representation of a real number. Represented as IEEE double.
foreign
Computer code expressed in languages other than Prolog. SWI-Prolog can only cooperate
directly with the C and C++ computer languages.
functor
Combination of name and arity of a compound term. The term foo(a, b, c) is said to be a term
belonging to the functor foo/3. foo/0 is used to refer to the atom foo.
goal
Question stated to the Prolog engine. A goal is either an atom or a compound term. A goal
either succeeds, in which case the variables in the compound terms have a binding, or it fails if
Prolog fails to prove it.
hashing
Indexing technique used for quick lookup.
head
Part of a clause before the neck operator (:-). This is an atom or compound term.
imported [predicate]
A predicate is said to be imported into a module if it is defined in another module and made
available in this module. See also chapter 6.
indexing
Indexing is a technique used to quickly select candidate clauses of a predicate for a specific
goal. In most Prolog systems, indexing is done (only) on the first argument of the head. If this
argument is instantiated to an atom, integer, float or compound term with functor, hashing is
used to quickly select all clauses where the first argument may unify with the first argument of
the goal. SWI-Prolog supports just-in-time and multi-argument indexing. See section 2.17.
integer
Whole number. On all implementations of SWI-Prolog integers are at least 64-bit signed
values. When linked to the GNU GMP library, integer arithmetic is unbounded. See also
current prolog flag/2, flags bounded, max integer and min integer.
interpreted
As opposed to compiled, interpreted means the Prolog system attempts to prove a goal by
directly reading the clauses rather than executing instructions from an (abstract) instruction set
that is not or only indirectly related to Prolog.
meta-predicate
A predicate that reasons about other predicates, either by calling them, (re)defining them or
querying properties.
mode [declaration]
Declaration of an argument instantiation pattern for a predicate, often accompanied with a
determinism.
module
Collection of predicates. Each module defines a name-space for predicates. built-in predicates
are accessible from all modules. Predicates can be published (exported) and imported to make
their definition available to other modules.
module transparent [predicate]
A predicate that does not change the context module. Sometimes also called a meta-predicate.
multi [determinism]
A predicate is said to have determinism multi if it generates at least one answer.
multifile [predicate]
Predicate for which the definition is distributed over multiple source files. See multifile/1.
neck
Operator (:-) separating head from body in a clause.
nondet
Short for non deterministic.
non deterministic
A non deterministic predicate is a predicate that mail fail or succeed any number of times.
operator
Symbol (atom) that may be placed before its operand (prefix), after its operand (postfix) or
between its two operands (infix).
In Prolog, the expression a+b is exactly the same as the canonical term +(a,b).
operand
Argument of an operator.
precedence
The priority of an operator. Operator precedence is used to interpret a+b*c as
+(a, *(b,c)).
predicate
Collection of clauses with the same functor (name/arity). If a goal is proved, the system looks
for a predicate with the same functor, then uses indexing to select candidate clauses and then
tries these clauses one-by-one. See also backtracking.
predicate indicator
Term of the form Name/Arity (traditional) or Name//Arity (ISO DCG proposal), where Name
is an atom and Arity a non-negative integer. It acts as an indicator (or reference) to a predicate
or DCG rule.
priority
In the context of operators a synonym for precedence.
program
Collection of predicates.
property
Attribute of an object. SWI-Prolog defines various * property predicates to query the status of
predicates, clauses. etc.
prove
Process where Prolog attempts to prove a query using the available predicates.
public list
List of predicates exported from a module.
query
See goal.
retract
Remove a clause from a predicate. See also dynamic, update view and assert.
semidet
Shorthand for
semi deterministic
.
semi deterministic
A predicate that is semi deterministic either fails or succeeds exactly once without a choice
point. See also deterministic.
shared
Two variables are called shared after they are unified. This implies if either of them is bound,
the other is bound to the same value:
?- A = B, A = a.
A = B, B = a.
singleton [variable]
Variable appearing only one time in a clause. SWI-Prolog normally warns for this to avoid
you making spelling mistakes. If a variable appears on purpose only once in a clause, write
it as _ (see anonymous). Rules for naming a variable and avoiding a warning are given in
section 2.15.1.
solution
Bindings resulting from a successfully proven goal.
structure
Synonym for compound term.
string
Used for the following representations of text: a packed array (see section 5.2, SWI-Prolog
specific), a list of character codes or a list of one-character atoms.
succeed
A goal is said to have succeeded if it has been proven.
term
Value in Prolog. A term is either a variable, atom, integer, float or compound term. In addition,
SWI-Prolog also defines the type string.
transparent
See module transparent.
unify
Prolog process to make two terms equal by assigning variables in one term to values at the
corresponding location of the other term. For example:
Unlike assignment (which does not exist in Prolog), unification is not directed.
update view
How Prolog behaves when a dynamic predicate is changed while it is running. There are two
models. In most older Prolog systems the change becomes immediately visible to the goal, in
modern systems including SWI-Prolog, the running goal is not affected. Only new goals see
the new definition.
variable
A Prolog variable is a value that is not yet bound. After binding a variable, it cannot be
modified. Backtracking to a point in the execution before the variable was bound will turn it
back into a variable:
?- A = b, A = c.
false.
?- (A = b; true; A = c).
A = b ;
true ;
A = c .
This, unfortunately, does not mean you can any version of SWI-Prolog under the above license.
The SWI-Prolog core may be linked to libraries that are more restrictive and in addition your code
may have loaded extension packages that have more restrictive conditions. In particular, the core is
by default linked to libgmp, distributed under the Lesser GNU Public license.
The above implies you need to configure and recompile the system without these components.
For this we provide options to the configure script:
./configure --without-gpl
./configure --without-lgpl
1
Actually pre-release 7.3.33
The GNU MP Bignum Library provides unbounded integers, rational numbers and some crypto-
graphical functionality. As libgmp is provided under the Lesser GNU Public license it may legally be
combined with proprietary software as long as libgmp is dynamically linked (default) and the end user
can replace the libgmp shared object and use your application with their (possibly modified) version
of libgmp. In practice this leads to problems if the application is not accessible (e.g., embedded in
closed hardware) or you want to avoid customers to peek around in the process memory as they can
easily do so by adding a backdoor to the modified LGPL component. Note that such a protection is
in general not possible anyway if the customer has unrestricted access to the machine on which the
application runs.
license
Evaluate the license conditions of all loaded components. If the system contains one or more
components that are licenced under GPL-like restrictions the system indicates this program
may only be distributed under the GPL license as well as which components prohibit the use of
other license conditions. Likewise for for LGPL components.
license(+LicenseId, +Component)
Register the fact that Component is distributed under a license identified by LicenseId. Known
license identifiers can be listed using known licenses/0. A new license can be registered
as a known language using a declaration like below. The second argument defines the category
if the license, which is one of gpl, lgpl, permissive or proprietary.
:- multifile license:license/3.
license:license(mylicense, permissive,
[ comment(My personal license),
url(http://www.mine.org/license.html)
]).
:- license(mylicense).
license(+LicenseId)
Intended as a directive in Prolog source files. It takes the current filename and calls
license/2.
known licenses
List all licenses known to the system. This does not imply the system contains code covered by
the listed licenses. See license/2.
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
DISCLAIMER
F.2.2 library(apply)
F.2.3 library(assoc)
F.2.4 library(broadcast)
F.2.5 library(charsio)
F.2.6 library(check)
F.2.7 library(clpb)
F.2.8 library(clpfd)
F.2.9 library(clpqr)
F.2.10 library(csv)
F.2.11 library(debug)
F.2.12 library(error)
current type/3 True when Type is a currently defined type and Var satisfies Type of the body term Body succee
domain error/2 The argument is of the proper type, but has a value that is outside the supported values.
existence error/2 Term is of the correct type and correct domain, but there is no existing (external) resource that i
has type/2 True if Term satisfies Type.
instantiation error/1 An argument is under-instantiated.
is of type/2 True if Term satisfies Type.
must be/2 True if Term satisfies the type constraints for Type.
permission error/3 It is not allowed to perform Action on the object Term that is of the given Type.
representation error/1 A representation error indicates a limitation of the implementation.
resource error/1 A goal cannot be completed due to lack of resources.
syntax error/1 A text has invalid syntax.
type error/2 Tell the user that Term is not of the expected Type.
uninstantiation error/1 An argument is over-instantiated.
F.2.13 library(iostream)
F.2.14 library(summaries.d/iostream/tex)
F.2.15 library(lists)
F.2.16 library(option)
F.2.17 library(optparse)
F.2.18 library(ordsets)
F.2.19 library(persistency)
current persistent predicate/1 True if PI is a predicate that provides access to the persistent database DB.
db attach/2 Use File as persistent database for the calling module.
db detach/0 Detach persistency from the calling module and delete all persistent clauses from the Pro
db sync/1 Synchronise database with the associated file.
db sync all/1 Sync all registered databases.
persistent/1 Declare dynamic database terms.
F.2.21 library(prologpack)
F.2.22 library(prologxref)
F.2.23 library(pairs)
group pairs by key/2 Group values with equivalent (==/2) consecutive keys.
map list to pairs/3 Create a Key-Value list by mapping each element of List.
pairs keys/2 Remove the values from a list of Key-Value pairs.
pairs keys values/3 True if Keys holds the keys of Pairs and Values the values.
pairs values/2 Remove the keys from a list of Key-Value pairs.
transpose pairs/2 Swap Key-Value to Value-Key.
F.2.24 library(pio)
library(pure input)
phrase from file/2 Process the content of File using the DCG rule Grammar.
phrase from file/3 As phrase from file/2, providing additional Options.
phrase from stream/2 Run Grammer against the character codes on Stream.
stream to lazy list/2 Create a lazy list representing the character codes in Stream.
lazy list character count//1 True when CharCount is the current character count in the Lazy list.
lazy list location//1 Determine current (error) location in a lazy list.
syntax error//1 Throw the syntax error Error at the current location of the input.
F.2.25 library(random)
F.2.26 library(readutil)
F.2.27 library(record)
F.2.28 library(registry)
This library is only available on Windows systems.
F.2.29 library(simplex)
F.2.30 library(ugraphs)
F.2.31 library(url)
distinct/1 True if Goal is true and no previous solution of Goal bound Witness to the same value.
distinct/2 True if Goal is true and no previous solution of Goal bound Witness to the same value.
group by/4 Group bindings of Template that have the same value for By.
limit/2 Limit the number of solutions.
offset/2 Ignore the first Count solutions.
order by/2 Order solutions according to Spec.
F.2.35 library(varnumbers)
max var number/3 True when Max is the max of Start and the highest numbered $VAR(N) term.
numbervars/1 Number variables in Term using $VAR(N).
varnumbers/2 Inverse of numbervars/1.
varnumbers/3 Inverse of numbervars/3.
varnumbers names/3 If Term is a term with numbered and named variables using the reserved term $VAR(X), Copy
F.2.36 library(yall)
*/2 Multiplication
**/2 Power function
+/1 Unary plus (No-op)
+/2 Addition
-/1 Unary minus
-/2 Subtraction
//2 Division
///2 Integer division
/\/2 Bitwise and
<</2 Bitwise left shift
>>/2 Bitwise right shift
./2 List of one character: character code
\/1 Bitwise negation
\//2 Bitwise or
/2 Power function
abs/1 Absolute value
acos/1 Inverse (arc) cosine
acosh/1 Inverse hyperbolic cosine
asin/1 Inverse (arc) sine
asinh/1 Inverse (arc) sine
atan/1 Inverse hyperbolic sine
atan/2 Rectangular to polar conversion
atanh/1 Inverse hyperbolic tangent
atan2/2 Rectangular to polar conversion
ceil/1 Smallest integer larger than arg
ceiling/1 Smallest integer larger than arg
cos/1 Cosine
cosh/1 Hyperbolic cosine
copysign/2 Apply sign of N2 to N1
cputime/0 Get CPU time
div/2 Integer division
e/0 Mathematical constant
erf/1 Gauss error function
erfc/1 Complementary error function
epsilon/0 Floating point precision
eval/1 Evaluate term as expression
exp/1 Exponent (base e)
float/1 Explicitly convert to float
float fractional part/1 Fractional part of a float
float integer part/1 Integer part of a float
floor/1 Largest integer below argument
gcd/2 Greatest common divisor
getbit/2 Get bit at index from large integer
inf/0 Positive infinity
F.4 Operators
[Bowen et al., 1983] D. L. Bowen, L. M. Byrd, and WF. Clocksin. A portable Prolog com-
piler. In L. M. Pereira, editor, Proceedings of the Logic Programming
Workshop 1983, Lisabon, Portugal, 1983. Universidade nova de Lisboa.
[Bratko, 1986] I. Bratko. Prolog Programming for Artificial Intelligence. Addison-
Wesley, Reading, Massachusetts, 1986.
[Butenhof, 1997] David R. Butenhof. Programming with POSIX threads. Addison-Wes-
ley, Reading, MA, USA, 1997.
[Byrd, 1980] L. Byrd. Understanding the control flow of Prolog programs. Logic
Programming Workshop, 1980.
[Clocksin & Melish, 1987] W. F. Clocksin and C. S. Melish. Programming in Prolog. Springer-
Verlag, New York, Third, Revised and Extended edition, 1987.
[Demoen, 2002] Bart Demoen. Dynamic attributes, their hProlog implementation,
and a first evaluation. Report CW 350, Department of Com-
puter Science, K.U.Leuven, Leuven, Belgium, oct 2002. URL =
http://www.cs.kuleuven.ac.be/publicaties/rapporten/cw/CW350.abs.html.
[Desouter et al., 2015] Benoit Desouter, Marko van Dooren, and Tom Schrijvers. Tabling as a
library with delimited control. TPLP, 15(4-5):419433, 2015.
[Freire et al., 1997] Juliana Freire, David S. Warren, Konstantinos Sagonas, Prasad Rao,
and Terrance Swift. XSB: A system for efficiently computing well-
founded semantics. In Proceedings of LPNMR 97, pages 430440,
Berlin, Germany, jan 1997. Springer Verlag. LNCS 1265.
[Fruhwirth, ] T. Fruhwirth. Thom Fruehwirths constraint handling rules website.
http://www.constraint-handling-rules.org.
[Fruhwirth, 2009] T. Fruhwirth. Constraint Handling Rules. Cambridge University Press,
2009.
[Graham et al., 1982] Susan L. Graham, Peter B. Kessler, and Marshall K. McKusick. gprof:
a call graph execution profiler. In SIGPLAN Symposium on Compiler
Construction, pages 120126, 1982.
[Hodgson, 1998] Jonathan Hodgson. validation suite for conformance with part 1 of
the standard, 1998, http://www.sju.edu/jhodgson/pub/
suite.tar.gz.
[Holzbaur, 1992] Christian Holzbaur. Metastructures versus attributed variables in the
context of extensible unification. In PLILP, volume 631, pages 260
268. Springer-Verlag, 1992. LNCS 631.
[Kernighan & Ritchie, 1978] B. W. Kernighan and D. M. Ritchie. The C Programming Language.
Prentice-Hall, Englewood Cliffs, New Jersey, 1978.
[Neumerkel, 1993] Ulrich Neumerkel. The binary WAM, a simplified Prolog en-
gine. Technical report, Technische Universitat Wien, 1993.
http://www.complang.tuwien.ac.at/ulrich/papers/PDF/binwam-
nov93.pdf.
[OKeefe, 1990] R. A. OKeefe. The Craft of Prolog. MIT Press, Massachussetts, 1990.
[Qui, 1997] AI International ltd., Berkhamsted, UK. Quintus Prolog, User Guide
and Reference Manual, 1997.
[Schimpf, 2002] Joachim Schimpf. Logical loops. In PeterJ. Stuckey, editor, Logic Pro-
gramming, volume 2401 of Lecture Notes in Computer Science, pages
224238. Springer Berlin Heidelberg, 2002.
[Schrijvers et al., 2013] Tom Schrijvers, Bart Demoen, Benoit Desouter, and Jan Wielemaker.
Delimited continuations for prolog. TPLP, 13(4-5):533546, 2013.
[Sterling & Shapiro, 1986] L. Sterling and E. Shapiro. The Art of Prolog. MIT Press, Cambridge,
Massachusetts, 1986.
[Triska, 2016] Markus Triska. The Boolean constraint solver of SWI-Prolog: System
description. In FLOPS, volume 9613 of LNCS, pages 4561, 2016.
https://www.metalevel.at/swiclpb.pdf.
xor/2, 182
xref built in/1, 473
xref called/3, 472
xref clean/1, 472