Web Prolog manual
This manual describes the Web Prolog language and APIs implemented by the
current demonstrator. It should be read as a snapshot of a design in
progress, not as a final language specification: terminology, predicate
interfaces, and behaviour are still tentative and may change as the
implementation evolves.
The classification shown beside each entry identifies the minimum public
node profile in which the predicate is available, or another relevant
execution context. ISOBASE provides general stateless Prolog calls,
ISOTOPE adds persistent toplevel sessions, and ACTOR adds the full stateful
actor-messaging model. The profiles are cumulative, so an entry marked
isotope is also available in ACTOR.
The classification concerns the client language, not predicates used
internally to implement a profile. Entries additionally marked
owner only are reserved for code
running with node-owner authority and are not available to ordinary client
code.
This document reproduces the book's manual appendix in HTML form. Each
predicate entry carries an HTML anchor using its
predicate indicator so that entries can be linked directly.
Predicates for programming with core actors
self(-Pid) is det.
Binds Pid to the process identifier of the calling process.
Note: A pid is an opaque capability value. Programs must not inspect it, perform arithmetic on it, or construct one from its printed components. Its canonical presentation is Id@Node; a shell may omit @Node for a pid on the shell's own node, but this changes only presentation. Browser runtimes reserve localhost as the local-node designator. Worker actors are therefore presented as, for example, 2159438818@localhost, and the optional main-thread SWI-WASM engine is presented as main@localhost.
Predicate: spawn/1-3
actor
spawn(+Goal) is det.
spawn(+Goal, -Pid) is det.
spawn(+Goal, -Pid, +Options) is det.
Creates a new Web Prolog actor process running Goal. Valid options are:
node(+URI)
Creates the process locally or on a remote compatible node. Default is localhost.
monitor(+Boolean)
If true, monitoring is installed as part of process creation. Default is false.
link(+Boolean)
If true, installs directional parent-to-child link cleanup. Default is true.
src_text(+AtomOrString)
Loads the clauses specified by a Web Prolog source text into the actor's private Prolog database before calling Goal.
src_list(+ListOfClauses)
Converts the clauses to source text and loads them into the actor's private Prolog database before calling Goal.
src_uri(+URI)
Loads the clauses specified by a file path, file URI, or HTTP(S) URI into the actor's private Prolog database before calling Goal.
src_predicates(+ListOfPredicateIndicators)
Loads the local predicates denoted by ListOfPredicateIndicators into the actor's private Prolog database before calling Goal.
Note: In spawn(+Goal,-Pid,+Options), the option monitor(true) installs monitoring as part of process creation. When the child terminates, the parent receives a message down(Pid,Ref,Reason) where Pid is the terminated actor, Reason is its exit reason, and Ref identifies the monitor instance. For monitoring created via monitor(true), the current implementation uses Ref = Pid.
Note: The semantics of link(true) are directional: if a parent spawns a child with linking enabled, termination of the parent causes linked children to be terminated. The link does not imply symmetric bidirectional exit propagation.
Note: It is possible to pass an arbitrary number of the src_* options to spawn/3, and possibly more than one instance of each variant. To ensure that clauses end up in a well-defined order, they are converted into Prolog source text before being loaded into the database. The order of clauses and directives in the resulting source text is determined by the order of the src_* options in the option list.
Predicate: actors/1
actor
actors(-Pids) is det.
Binds Pids to the list of actor pids visible from the current execution context. In ordinary public client execution, this means the current actor or toplevel together with any actors that have been spawned on behalf of the same client interaction. Actors belonging to other clients are not included.
Note: Outside public client execution, for example in node-owned runtime code or administrative code, actors/1 returns the pids of all active local actors on the node.
Predicate: monitor/2
actor
monitor(+PidOrName, -Ref) is det.
Installs a monitor and returns a fresh reference in Ref. The first argument may be a pid or a registered local name. When the monitored process terminates, the monitoring process receives a message of the form down(Pid,Ref,Reason).
Note: Using monitor(true) in spawn/3 is the safest variant for short-lived children, since monitoring is established during spawn. Installing monitoring later with monitor/2 is a separate step and may miss a child that exits immediately.
Predicate: demonitor/1-2
actor
demonitor(+Ref) is det.
demonitor(+Ref, +Options) is det.
Stops monitoring identified by Ref. This is idempotent. There is only one valid option:
flush
Non-blocking removal of all pending down(_,Ref,_) messages from the mailbox.
Predicate: register/2
actor
register(+Name, +Pid) is det.
Registers an actor process under a name, where Name is an atom and Pid identifies the actor. The association between the name and the pid is removed when the process terminates.
Predicate: whereis/2
actor
whereis(+Name, -Pid) is det.
Binds Pid to the actor process associated with Name, or to undefined if no such registration exists.
Predicate: unregister/1
actor
unregister(+Name) is det.
Removes the association between the name and the process. The actor itself is not terminated. The operation is idempotent and succeeds without effect if Name is not registered.
Predicate: register_service/2
actor, owner only
register_service(+Name, +Pid) is det.
Publishes the live local actor identified by Pid under Name in the node's public service namespace. Name must be an atom, Pid must identify an actor on the publishing node, and there may be at most one published service with a given name on a node. If the name is already published, register_service/2 raises permission_error(register,service,Name), even when the existing entry denotes the same actor. Replacement is therefore explicit: the owner must first withdraw the old mapping.
The public service namespace is distinct from the ordinary registration namespace used by register/2; the same atom may occur in both without a collision. A qualified address Name@Node is resolved against the public service namespace of Node. whereis/2 consults only the ordinary namespace; owner-side code may inspect the service namespace with whereis_service/2.
Publication neither changes the actor's links nor places it under supervision. In particular, register_service/2 does not detach the actor from its parent. When the actor terminates, the node controller removes the service mapping atomically, so a published name never remains bound to a dead pid. A supervisor that starts a replacement actor must publish that actor again under the stable name.
Only code executing with node-owner authority may call this predicate. A call by any other principal raises permission_error(register,service,Name). A non-atom Name raises type_error(atom,Name); a Pid that does not identify a live actor raises existence_error(process,Pid); and an attempt to publish an actor on another node raises permission_error(register,service,Pid).
Predicate: whereis_service/2
actor, owner only
whereis_service(+Name, -Pid) is det.
Binds Pid to the live local actor published as Name, or to undefined if no such service is published. This predicate inspects only the public service namespace.
Only code executing with node-owner authority may call it; other callers receive permission_error(access,actor_service_registry,whereis_service(Name,Pid)). A non-atom Name raises type_error(atom,Name).
Predicate: unregister_service/1
actor, owner only
unregister_service(+Name) is det.
Withdraws Name from the node's public service namespace. This removes only the name: it neither terminates nor otherwise changes the actor that the name denoted. The operation is idempotent and succeeds without effect when no such service is published.
Only code executing with node-owner authority may call this predicate; other callers receive permission_error(unregister,service,Name). A non-atom name raises type_error(atom,Name).
exit(+Reason) is det.
Terminates the calling process with Reason.
exit(+Pid, +Reason) is det.
Terminates the process identified by Pid with Reason. For remote actors, the runtime routes this request through the remote node.
Predicate: !/2, send/2-3
actor
+PidOrName ! +Message is det.
send(+PidOrName, +Message) is det.
send(+PidOrName, +Message, +Options) is det.
Sends Message to the mailbox of the process identified as PidOrName. PidOrName may be a local pid, a local registered name, a global pid of the form Id@Node, or a published service address of the form Name@Node. Qualified service addresses are resolved only through the destination node's live service registry. If such a service is absent or the sender is not authorised to use it, the send succeeds without delivery and does not reveal which condition applied. By contrast, an unknown local registered name raises existence_error(actor_name,Name); a send to an unknown pid succeeds without delivery. Valid options for send/3 are:
delay(+Number)
Delays the sending by a specified number of seconds. Default is 0.
id(+ID)
ID is a user-supplied identifier that can be used by cancel/1 to stop the sending from taking place.
Portable actor application messages are acyclic ordinary Prolog terms. Atoms, strings, numbers, variables, lists, and compound terms are portable; variables arrive as fresh variables. Attributed variables, streams, and other non-text blob values must be encoded explicitly by the application. The demonstrator validates this subset whenever serialization is required. Native local delivery may happen to carry additional host terms, but programs using them are outside the placement-independent contract.
Predicate: cancel/1
actor
cancel(+ID) is det.
Tries to cancel the sending of all delayed messages with the specified ID. This is best-effort only, since a message may already have been sent by the time the call is made.
Predicate: output/1-2
actor
output(+Data) is det.
output(+Data, +Options) is det.
Sends a message output(Pid,Data) to the target process. Pid is the pid of the current process. Valid option:
target(+Pid)
Send the message to Pid. Default is the parent process.
Note that this is just a convenience predicate. A toplevel, like any other actor, may use !/2 to send any term to any process to which it has a pid.
Predicate: input/2-3
actor
input(+Prompt, -Data) is det.
input(+Prompt, -Data, +Options) is det.
Sends a message prompt(Pid,Prompt) to the target process and waits for its input. Prompt may be any Prolog term. Pid is the pid of the current process. Data will be bound to the term that the target process sends using respond/2. Valid option:
target(+Pid)
Send the prompt message to Pid. Default is the current I/O target when one has been installed, or otherwise the parent process.
Predicate: respond/2
actor
respond(+Pid, +Input) is det.
Sends Input to the process identified by Pid as a response to a prompt(Pid,Prompt) message.
Predicate: receive/1-2
actor
receive(+Clauses) is nondet.
receive(+Clauses, +Options) is nondet.
Waits for, selects, and consumes one message from the calling process's mailbox. A call is single-message, but not necessarily single-solution. During one invocation it selects and consumes at most one message. Messages are considered in arrival order, and each message is tested against the receive clauses in textual order. The first message accepted by a clause is removed from the mailbox. This selection is committed: backtracking through the invocation never selects another message or another clause.
The selected clause body is ordinary Prolog code. The call as a whole therefore has the determinism of the fired body: a body may fail, succeed once, throw an exception, or yield several solutions. Choice points left by the body remain available, but they enumerate solutions of that same body; they do not inspect the mailbox again. The selected message remains consumed if the body fails or throws, and is not restored on backtracking. Thus the nondet declaration concerns the possible number of logical solutions, not the number of messages consumed by one invocation. For example, after one foo message has arrived, receive({foo -> member(X, [a,b])}) consumes that message once but can yield both X = a and X = b.
Clauses has the following form:
{ Pattern1 [if Guard1] ->
Body1 ;
...
PatternN [if GuardN] ->
BodyN
}
A clause accepts a message if the message unifies with its pattern and its optional guard succeeds. A guard is evaluated for its first solution only, as if by once/1, and should be free of side effects. Bindings from the pattern and guard are in scope in the body. If a guard fails or raises an exception, that clause does not accept the message.
Messages accepted by no clause are deferred: they remain in the mailbox, without any change in their contents or relative order, and are available to later receive calls. receive({}) accepts no message and waits, subject to Options. Valid options:
timeout(+Number)
Bounds the wait for an accepted message, in seconds. The value 0 inspects messages already in the mailbox without waiting for another. Default is no timeout.
on_timeout(+Goal)
Called if the timeout expires with no message accepted. Its success, failure, exception, and any choice points determine the outcome of the receive on the timeout path. Default is true. This option is only meaningful when timeout/1 is present.
flush is det.
Removes all messages currently pending in the mailbox of the calling process. Each removed message is rendered through the actor terminal-output path as a line of the form Shell got Message, where Message is the full Prolog term.
Note: flush/0 is primarily a shell-level inspection utility. It does not wait for future messages: once the mailbox is empty at the time of the call, it succeeds immediately.
Predicate: listing/0-1
isotope
listing is det.
listing(+What) is det.
listing/0 lists the content of the private database of the current actor process through the terminal-output path. Imported predicates and the injected I/O wrapper predicates are omitted.
listing/1 lists the predicates or clauses in the current process's private database selected by What, following the conventional Prolog meaning of listing/1. What may be a predicate indicator (Name/Arity or Name//Arity), a callable head pattern, a clause reference, or a list of such specifications. It does not provide access to another actor's private database.
Predicates for programming with toplevel actors
Predicate: toplevel_spawn/1-2
actor
toplevel_spawn(-Pid) is det.
toplevel_spawn(-Pid, +Options) is det.
Spawns a toplevel actor and binds Pid to its pid. All options accepted by spawn/3 are also accepted by toplevel_spawn/2. In addition, toplevel_spawn/2 accepts the following options:
session(+Boolean)
If set to false, the toplevel actor terminates after having run a goal to completion. If true, further interaction is expected. Default is false in the actor API.
target(+Pid)
Send all answer terms to Pid. Default is the pid of the parent.
name(+Name)
Register the toplevel actor under Name in the local ordinary-name namespace.
time_limit(+SecondsOrInfinite)
Bounds each continuous period spent executing a goal in PTCP state s2. On expiry the target receives error(Pid, time_limit_exceeded) and a session toplevel returns to s1, ready for another call. Time spent waiting for a continuation in s3 does not count; the running time limit starts again when a continuation resumes. Default is infinite in the actor API; a public node may impose a finite ceiling.
idle_limit(+SecondsOrInfinite)
Bounds inactivity while a session toplevel waits for a call in state s1 or a continuation in state s3. On expiry the actor terminates normally, so a monitor observes down(Pid, Ref, true). Default is infinite in the actor API; a public node may impose a finite ceiling.
Both finite lifecycle limits must be positive numbers of seconds. A public client may request tighter values, but cannot weaken the node owner's ceilings. These limits are distinct from an ISOTOPE session HTTP request's timeout, which only bounds how long that request waits for the next queued event and does not abort the goal or terminate the session.
Predicate: toplevel_call/2-3
actor
toplevel_call(+Pid, +Goal) is det.
toplevel_call(+Pid, +Goal, +Options) is det.
Asks the toplevel Pid for solutions to Goal. Valid options are:
template(+Template)
Template is a term sharing variables with Goal. By default, the template is identical to the goal.
offset(+Integer)
Collect only the slice of solutions starting from Integer. Default is 0.
limit(+Integer)
Restrict the length of the returned list of solutions to Integer.
once(+Boolean)
When true, commits to the first returned slice and reports More = false, even if Goal has further solutions. Default is false. This option is useful primarily with limit/1.
target(+Pid)
Send the answer term to Pid. Default is the value of target when passed as an option to toplevel_spawn/2.
Variables in Goal are not bound directly in the caller. Instead, solutions and other kinds of output are returned in the form of answer messages delivered to the mailbox of the target process:
success(Pid, Data, More)
Pid is the pid of the toplevel process that succeeded in finding solutions to Goal. Data is a list holding instantiations of Template. More is either true or false, indicating whether the toplevel can return more solutions if toplevel_next/1-2 is called.
failure(Pid)
Pid is the pid of the toplevel process that failed for lack of solutions.
error(Pid, Data)
Pid is the pid of the toplevel throwing the error. Data is the error term.
Predicate: toplevel_next/1-2
actor
toplevel_next(+Pid) is det.
toplevel_next(+Pid, +Options) is det.
Asks toplevel Pid for more solutions. Valid options:
limit(+Integer)
If omitted, the actor API keeps using the most recent limit value from the previous toplevel call state.
target(+Pid)
Send the answer term to Pid. Default is the value of target from the previous call state.
The messages delivered to the target mailbox are the same as for toplevel_call/2-3.
Predicate: toplevel_stop/1
actor
toplevel_stop(+Pid) is det.
Asks toplevel Pid to stop searching for more solutions.
Predicate: toplevel_abort/1
actor
toplevel_abort(+Pid) is det.
Tells the local toplevel Pid to abort the execution of the currently running goal. An unknown or non-local pid has no effect.
Predicate: toplevel_halt/1-2
actor
toplevel_halt(+Pid) is det.
toplevel_halt(+Pid, -Reply) is det.
Terminates toplevel actor Pid from any protocol state. The one-argument form requests termination through the actor runtime and returns without waiting for confirmation. The two-argument form installs a private monitor, requests termination, and waits until termination has been observed; it then unifies Reply with true.
Note: The private monitor used by toplevel_halt/2 is distinct from any existing monitor. If the toplevel was spawned with monitor(true), the caller still receives its original down(Pid, Pid, true) notification.
Predicates for programming with server actors
Predicate: server_spawn/3-4
actor
server_spawn(+Pred, +State, -Pid) is det.
server_spawn(+Pred, +State, -Pid, +Options) is det.
Spawns a generic server actor using callback predicate Pred/4 and initial state State. The callback receives (Request, OldState, Response, NewState).
All options are forwarded to spawn/3 except:
name(+Name)
Register the server under Name.
Predicate: server_request/3-4
actor
server_request(+To, +Request, -Response) is det.
server_request(+To, +Request, -Response, +Options) is det.
Makes a synchronous request-response call to the server To, where To may be a pid or a registered local name. server_request/4 accepts the options of receive/2, for example timeout(+Seconds).
Monitoring is installed automatically so the call fails fast if the server terminates before replying.
Predicate: server_promise/3-4
actor
server_promise(+To, +Request, -Ref) is det.
server_promise(+To, +Request, -Ref, -MonRef) is det.
Sends Request to the server To and returns a correlation reference Ref. The reply must later be collected with server_yield/2-4.
The four-argument variant additionally installs a monitor and returns its reference in MonRef.
Predicate: server_yield/2-4
actor
server_yield(+Ref, -Response) is det.
server_yield(+Ref, -Response, +Options) is det.
server_yield(+Ref, +MonRef, -Response, +Options) is det.
Waits for the response matching Ref. The three-argument variant accepts the options of receive/2.
The four-argument variant uses MonRef to detect server termination, removes that monitor after a normal reply, and throws server_down(Reason) if the server dies before replying.
Predicate: server_upgrade/2-3
actor
server_upgrade(+To, +Pred) is det.
server_upgrade(+To, +Pred, +Options) is det.
Replaces the callback predicate of the running server To without disturbing its current state. Pred must denote a callback predicate of arity four.
The two-argument form transfers no code and requires the callback to be present already in the server's private database. The three-argument form loads callback source using src_text/1, src_list/1, src_predicates/1, or src_uri/1.
The operation replies only after the callback has been loaded and validated. It preserves the current state value and performs no state migration. If installation fails, server_upgrade/2-3 rethrows the reported error and the state is unchanged. Source changes made in the server's private database before the error are not rolled back.
Predicate: server_halt/2
actor
server_halt(+To, -Reply) is det.
Asks the server To to stop gracefully and binds Reply to its acknowledgement.
Predicates for programming with statechart actors
Predicate: statechart_spawn/2
actor
statechart_spawn(-Pid, +Options) is det.
Spawns a statechart actor and binds Pid to its pid.
statechart_spawn/2 requires exactly one source option:
src_uri(+URI)
Load and run a statechart from a URI or file path.
src_text(+Text)
Load and run a statechart from an XML text string.
In addition, statechart_spawn/2 accepts:
name(+Name)
Register the statechart actor under Name in the local ordinary-name namespace.
Statechart trace events are published automatically. The Logger's SXML trace filter controls their visibility; tutorial diagrams consume the same events for animation.
All remaining options are passed through to spawn/3.
src_list/1 and src_predicates/1 are rejected for statechart_spawn/2.
SXML supports state-scoped timed transitions:
<go to="Target" after="5">...</go>
The after value is a non-negative number of seconds. The timer is armed when the source state is entered and cancelled automatically when that state is left. Re-entry creates a fresh activation, so a late firing from an earlier activation is ignored. after may be combined with if, whose guard is tested when the timer fires, but it cannot be combined with on on the same transition.
SXML also supports state-scoped event deferral:
<defer on="command(C)" if="temporarily_unavailable(C)"/>
If no transition is enabled for an event, matching <defer> declarations are sought in the active configuration, from the innermost states outwards. A match postpones the event. After a macrostep changes the configuration, postponed events are re-offered oldest first on the internal event queue, before invocation or receipt of another external event. Enabled transitions always take precedence. An event that still matches a defer declaration may be postponed again; otherwise it is discarded if no transition accepts it. The optional if guard uses bindings from the on pattern. The postponed queue has no implicit size limit.
Predicate: statechart_halt/2-3
actor
statechart_halt(+Pid, -Reply) is det.
statechart_halt(+Pid, -Reply, +Timeout) is det.
Asks the statechart actor Pid to halt gracefully, running the exit actions of its active states, and waits for an acknowledgement in Reply. The two-argument form waits indefinitely.
The three-argument form waits at most Timeout seconds. If the actor does not reply in time, it is killed and Reply becomes killed.
Predicate: raise/1
statechart builtin
raise(+Event) is det.
Enqueues Event on the internal event queue of the current statechart interpreter.
Important: raise/1 is only meaningful inside executable statechart content such as <datamodel>, <onentry>, <onexit>, and <go>.
Predicate: in/1
statechart builtin
in(+Id) is semidet.
Succeeds if the state identified by Id belongs to the current active configuration of the statechart interpreter.
Important: in/1 is only meaningful inside statechart guards or executable statechart content such as <onentry>, <onexit>, and <go>.
Predicates for programming with supervisor actors
Predicate: supervisor_spawn/2-3
actor
supervisor_spawn(+ChildSpecs, -Pid) is det.
supervisor_spawn(+ChildSpecs, -Pid, +Options) is det.
Spawns a supervisor actor and starts its children. Supported options are:
strategy(+Strategy)
One of one_for_one (default), one_for_all, or rest_for_one.
intensity(+Integer)
Maximum number of restarts permitted within one period. Default is 1.
period(+Integer)
Restart-intensity window in seconds. Default is 5.
name(+Name)
Register the supervisor under Name.
Other options are passed through to spawn/3.
Child specifications take the form child(Id, ChildOptions). Child options are:
start(+Goal)
Required. Start goal for the child. The special form server(Pred,ServerOptions) starts a generic server child. The default initial state is []. It may be replaced with initial_state(+State). All remaining ServerOptions are passed to server_spawn/4.
restart(+Policy)
One of permanent (default), transient, or temporary.
shutdown(+Shutdown)
One of brutal_kill, infinity, or a timeout in seconds. The default is 5 for workers and infinity for supervisor children.
type(+Type)
worker (default) or supervisor.
Predicate: supervisor_spawn_child/3
actor
supervisor_spawn_child(+Pid, +ChildSpec, -Reply) is det.
Dynamically adds and starts one child. On success, Reply is ok. If a child with the same Id is already present, it is error(already_present). If startup fails, it is error(start_failed).
Predicate: supervisor_terminate_child/3
actor
supervisor_terminate_child(+Pid, +Id, -Reply) is det.
Stops child Id but keeps its specification. Reply is ok or error(not_found).
Predicate: supervisor_delete_child/3
actor
supervisor_delete_child(+Pid, +Id, -Reply) is det.
Removes a non-running child specification. Reply is ok, error(running), or error(not_found).
Predicate: supervisor_respawn_child/3
actor
supervisor_respawn_child(+Pid, +Id, -Reply) is det.
Restarts a previously terminated child from its stored specification. Reply is either ok(NewPid), error(running), error(not_found), or error(start_failed).
Predicate: supervisor_which_children/2
actor
supervisor_which_children(+Pid, -Children) is det.
Returns a list of:
info(Id, Pid, Type, Restart)
where Pid may be undefined for stopped children.
Predicate: supervisor_count_children/2
actor
supervisor_count_children(+Pid, -Counts) is det.
Returns:
[specs-N, active-N, supervisors-N, workers-N]
Predicate: supervisor_halt/1
actor
supervisor_halt(+Pid) is det.
Stops the supervisor and shuts down children in reverse start order.
Note on synchronous supervisor calls
The dynamic/query API above uses monitored synchronous calls and may throw:
supervisor_down(Reason)
supervisor_call_timeout(Sup, Request)
Actor-based predicate generics
Predicate: parallel/1
actor
parallel(+Goals) is semidet.
Runs the proper list of independent goals Goals concurrently, using one monitored worker actor per goal. The call succeeds when every goal has produced its first solution and returns the resulting variable bindings. parallel([]) succeeds immediately. Further solutions are not enumerated on backtracking.
If any goal fails, the remaining workers are terminated and the call fails. If any goal throws an exception, the remaining workers are terminated and the exception is rethrown. Result and monitor messages belonging to the workers are removed before the predicate returns, fails, or throws.
The goals must not depend on bindings or side effects produced by sibling goals. Actor creation and message copying add overhead, and the one-worker-per-goal model gives large goal lists a correspondingly large resource footprint.
A non-list Goals raises type_error(list, Goals). An element that is not callable raises the corresponding callable type error from its worker, which is propagated to the caller.
Predicate: first_solution/2-3
actor
first_solution(?Solution, +Goals) is semidet.
first_solution(?Solution, +Goals, +Options) is semidet.
Runs the proper list of alternative goals Goals concurrently in monitored worker actors and unifies Solution with the result produced by the first solver to succeed. Once a winner has been selected, all remaining workers are terminated and their result and monitor messages are removed. The predicate does not enumerate later solutions on backtracking, and an empty goal list fails.
The two-argument form continues after an individual solver fails and stops on the first exception. The three-argument form accepts:
on_fail(stop|continue)
continue removes the failed solver and keeps waiting while alternatives remain; stop terminates all workers and fails immediately. Default is continue.
on_error(stop|continue)
continue removes the solver that raised an exception and keeps waiting while alternatives remain; stop terminates all workers and rethrows the exception. Default is stop.
If all alternatives are removed under a continue policy, the predicate fails. Goals should not depend on side effects produced by sibling solvers.
A non-list Goals or Options raises type_error(list, Term). An action other than stop or continue raises type_error(oneof([stop,continue]), Action). An unknown option raises domain_error(first_solution_option, Option).
Predicates for remote Prolog-style calls
Predicate: rpc/2-3
isobase
rpc(+URI, +Goal) is nondet.
rpc(+URI, +Goal, +Options) is nondet.
Executes a copy of Goal through the stateless /call endpoint of the node identified by URI, then unifies the local goal with each returned solution on backtracking. This remains a stateless call even when the destination is an ACTOR node: actor-only predicates such as self/1, spawn/1-3, and receive/1-2 are not available through rpc/2-3.
The first argument alone selects the execution node. localhost means the node on which rpc/2-3 is running. Source-loading options supply source for the call's temporary private database and do not change that target. For example, rpc('https://n2.example',Goal,[src_uri('https://n3.example')]) executes Goal on n2.example using source fetched from n3.example. All conforming native and browser runtimes accept:
limit(+Integer)
Restricts the number of solutions retrieved per roundtrip.
once(+Boolean)
When true, retrieves only the first slice and does not request later slices. Default is false.
timeout(+Number)
Requests a timeout in seconds for goal execution on the destination node. The effective timeout is the minimum of this value and the node owner's configured timeout.
http_timeout(+Number)
Sets the client-side HTTP transport timeout in seconds for each request. It does not change the destination node's execution timeout.
src_text(+AtomOrString)
Loads source text into the temporary private database before calling Goal.
src_list(+ListOfClauses)
Converts the clauses to source text and loads them into the temporary private database.
src_uri(+URI)
Fetches source from URI and loads it into the temporary private database. This URI is a source location only.
src_predicates(+ListOfPredicateIndicators)
Copies the caller's indicated predicates into the temporary private database.
Predicate: promise/3-4
isobase
promise(+URI, +Goal, -Ref) is det.
promise(+URI, +Goal, -Ref, +Options) is det.
Starts one asynchronous stateless call to node URI with Goal and returns a local promise reference in Ref. As with rpc/2-3, the first argument selects the execution node and localhost denotes the current node. Source-loading options populate the promised call's temporary private database; they do not change its execution node. It accepts the same limit/1, once/1, timeout/1, http_timeout/1, and src_*/1 options as rpc/3, together with:
template(+Template)
Template is a term sharing variables with the goal. By default, the template is identical to the goal.
offset(+Integer)
Selects the starting offset of the single solution slice collected by the promise. Default is 0.
The reference returned in Ref can later be used by yield/2-3 to collect the single answer term. Programs must not infer meaning from its digits or construct references themselves.
Predicate: yield/2-3
isobase
yield(+Ref, ?Answer) is det.
yield(+Ref, ?Answer, +Options) is det.
Waits for the answer term from a previous call to promise/3-4. The reference is local to the runtime that created it. The answer is one of success(Data,More), failure, or error(Error), as returned by the stateless call endpoint. Valid options are:
timeout(+Number)
Waits at most Number seconds for the promised answer. Default is no timeout.
on_timeout(+Goal)
Calls Goal if the timeout expires before the answer is available.
A timeout does not cancel or consume the promise; a later call with the same reference may collect an answer that arrives afterward. If on_timeout/1 is omitted, the timeout path succeeds.
Predicate: runtime_property/1
isobase
runtime_property(?Property) is nondet.
Enumerates properties of the host runtime. This predicate reports capabilities; it does not alter the Web Prolog profile or the semantics of the predicates above. Defined properties are:
implementation(swi_native|swi_wasm_worker|swi_wasm_main)
persistent(+Boolean)
inbound_addressable(+Boolean)
dom(+Boolean)
actor_isolation(native_thread|web_worker|cooperative_engine)
hard_termination(+Boolean)
Native nodes are persistent and inbound-addressable and use native threads with hard termination, but have no DOM. Worker SWI-WASM actors have Web-Worker isolation and hard termination but share the page's lifetime, are not inbound-addressable, and have no DOM. The optional main-thread SWI-WASM engine has DOM access but cooperative engine isolation and no hard termination; it too shares the page's lifetime and initiates rather than accepts remote connections.
ISO predicates and related constructs
The following ISO Prolog predicates and related constructs are available to clients of a Web Prolog node. Predicates that require direct stream or file access, module loading, runtime reflection, or parser state mutation are excluded by the sandbox.
Control Constructs
true/0, fail/0, call/1-8, !/0, (,)/2, (;)/2, (->)/2, (\+)/1, catch/3, throw/1
Directives
dynamic/1, multifile/1, discontiguous/1
Term Unification
(=)/2, (\=)/2, unify_with_occurs_check/2
Arithmetic Evaluation and Comparison
is/2, (=:=)/2, (=\=)/2, (<)/2, (>)/2, (>=)/2, (=<)/2
Arithmetic Functions
(+)/1-2, (-)/1-2, (*)/2, (//)/2, (/)/2, rem/2, mod/2, abs/1, sign/1, float_integer_part/1, float_fractional_part/1, float/1, truncate/1, round/1, ceiling/1, floor/1, max/2, min/2, (**)/2, sin/1, cos/1, atan/1, atan2/2, exp/1, log/1, sqrt/1, (>>)/2, (<<)/2, (/\)/2, (\/)/2, (\)/1, xor/2, pi/0
Term Comparison
(@<)/2, (@>)/2, (@>=)/2, (@=<)/2, compare/3
Type Testing
var/1, nonvar/1, atom/1, number/1, integer/1, float/1, compound/1, atomic/1, callable/1, ground/1
Term Creation and Decomposition
functor/3, arg/3, (=..)/2, copy_term/2
Clause Retrieval
clause/2
Clause Creation and Destruction
asserta/1, assertz/1, retract/1, abolish/1
All-Solutions
findall/3, bagof/3, setof/3
Actor I/O (Overrides)
The ambient stream I/O predicates of ISO Prolog are blacklisted. In their place, the actor runtime prelude injects local overrides that route output through the actor messaging layer:
nl/0, write/1, writeq/1, write_term/2, writeln/1, write_canonical/1, print/1, display/1, format/1-2
Atomic Term Processing
atom_length/2, atom_concat/3, atom_chars/2, atom_codes/2, sub_atom/5, char_code/2, number_chars/2, number_codes/2