This module contains predicates for working with definite clause
grammars and the related stateful programming style where state
arguments are automatically threaded through sequences
of calls. Some useful DCG procedures are also included.
When a predicate is declared with type foo(...)// is Det
,
any requirements on the type of the DCG state are hidden, i.e. the
types of the two extra arguments are hidden. In these cases,
the documentation below will sometimes state that the predicate
'runs in the S
DCG'.
Types used in this module
We use the following to denote types of terms that can
be interpreted as DCG phrases with or without further
arguments.
- phrase(S)
- If P is a term of type
phrase(S)
, then P is a valid DCG phrase
when the DCG state is of type S
, i.e. phrase(P,S1,S2)
is
valid Prolog goal when S1 and S2 are of type S
. N.B. the type
phrase(S)
is almost but not quite equivalent to the binary
predicate type pred(S,S)
. All such predicates are valid phrases,
but phrases involving braces (e.g. {Goal}), commas, semicolons,
and if-then constructs (->) are not equivalent to predicates
with two extra arguments.
- phrase(A, S)
- If P is of type
phrase(A,S)
and X has type A, then call(P,X)
is a valid DCG phrase when the DCG is of type S. This type is
equivalent to pred(A,S,S)
because the only way to call it
is with call//1 inside a DCG or call/3 outside it.
- phrase(A, B, S)
- If P is of type
phrase(A,B)
and X
and Y
are of types
A
and B
respectively, then call(P,X,Y)
is a valid DCG phrase. And so on. You get the idea.
- nop// is det
- Do nothing. (More neutral than []).
- trans(?Old:S, ?New:S, ?S1:int, ?S2:S) is det
- Unifies Old and New with the states S1 and S2 respectively.
- set(S:A, S1:_, S2:A) is det
- Set state to S.
- get(S:A, S1:A, S2:A) is det
- Get state to S.
- set_with(+G:pred(A), S1:_, S2:A) is det
- Set current state using a given callable goal G, which should accept one argument.
should be of type
pred( -S:A)
, ie it should set S to the new desired
state, which is installed in the DCG state.
- with(S:A, P:phrase(A), S1:B, S2:B) is nondet
- Run phrase P starting from state S and discarding
the final state, meanwhile preserving the state
of the current system, i.e. guarantees S1=S2.
- iso(P:phrase(A), S1:A, S2:A) is nondet
- Run phrase P starting with current state but discarding
its final state and preserving the current state, so
that S1=S2.
- once(G:phrase(_))// is semidet
- Call DCG phrase G succeeding at most once.
- repeat// is nondet
- Create an infinite number of choice points.
- fail// is nondet
- Fails immediately.
- freeze(@V:var, +G:phrase(A), ?S1:A, ?S2:A) is nondet
- Suspends the application of DCG goal G to S1 and S2 until variable V is instantiated.
- G1:phrase(S) >> G2:phrase(S)// is nondet
- Sequential conjuction of phrases G1 and G2, equivalent to (G1,G2),
but sometimes more convenient in terms of operator priorities.
- //(+P1:phrase(A), +P2:phrase(A), ?S1:A, ?S2:A) is nondet
- Parallel goal operator - succeeds if both phrases succeeds with the
same start and end states. P1 is called first.
Note, this can be used to capture the list
of terminals matched by another phrase by using
Phrase // list(Terms)
.
phrase P, eg.
?- phrase(paren(arb)//list(C),"(hello)world",_)
C = "(hello)".
true
- maybe(P:phrase(_))// is det
- Try P, if it fails, then do nothing. If it succeeds,
cut choicepoints and continue.
- opt(P:phrase(_))// is nondet
- P or nothing. Like maybe but does not cut if P succeeds.
- if(G:pred, P, Q)// is det
- if(G:pred, P)// is det
- If Prolog goal
call(G)
succeeds, do P, otherwise, do Q.
if(G,P)
is equivalent to if(G,P,nop)
, i.e. does nothing
if P fails.
- exhaust(P:phrase(_))// is det
- Run phrase sequentially as many times as possible until it fails.
Any choice points left by G are cut.
- until(+Q:pred, +P:phrase(_))// is det
- Repeatedly call phrase P and test ordinary Prolog goal
Q until Q fails. P and Q are copied together before each
iteration, so variables can be shared between them, but
are not shared between iterations.
- iterate(+P:phrase(A,A,S), +X:A, -Y:A)// is nondet
- Sequentially call P zero or more times, passing in X on
the first call and threading the result through subsequent calls,
(as well as threading the DCG state in the normal way)
ending in Y.
- rep(+N:natural, +P:phrase(_))// is nondet
- rep(-N:natural, +P:phrase(_))// is nondet
- Equivalent to N sequential copies of phrase P.
Free variables in P are not shared between copies.
If N is unbound on entry, rep//2 is cautious: it tries
gradually increasing N from 0 on backtracking.
- rep_with_sep(+Q:phrase(A), +N:natural, +P:phrase(A))// is nondet
- rep_with_sep(+Q:phrase(A), -N:natural, +P:phrase(A))// is nondet
- As rep//2, but repeats are interspersed with Q. N must be 1 or greater.
- rep_nocopy(+N:natural, +P:phrase(_))// is nondet
- Like rep//2 but does not copy P before calling, so
any variables in P are shared between all calls.
Also, N cannot be a variable in this implementation.
- seqmap(+P:phrase(A,S), X:list(A))// is nondet
- seqmap(+P:phrase(A,B,S), X:list(A), Y:list(B))// is nondet
- seqmap(+P:phrase(A,B,C,S), X:list(A), Y:list(B), Z:list(C))// is nondet
- seqmap(+P:phrase(A,B,C,D,S), X:list(A), Y:list(B), Z:list(C), W:list(D))// is nondet
- seqmap(+P:phrase(A,B,C,D,E,S), X:list(A), Y:list(B), Z:list(C), W:list(D), V:list(E))// is nondet
- seqmap//N is like maplist/N except that P is an incomplete phrase
rather an ordinary goal, which is applied to the elements of the supplied
lists in order, while threading the DCG state correctly through all
the calls.
seqmap//N is very powerful - it is like foldl
and mapaccum
in functional
languages, but with the added flexibility of bidirectional Prolog variables.
- See also
- - maplist/2.
- seqmap_n(+N:natural, +P:phrase(A), X:list(A))// is nondet
- seqmap_n(+N:natural, +P:phrase(A,B), X:list(A), Y:list(B))// is nondet
- seqmap_n(+N:natural, +P:phrase(A,B,C), X:list(A), Y:list(B), Z:list(C))// is nondet
- seqmap_n//.. is like seqmap/N except that the lists of arguments are of length N.
- seqmap_with_sep(+S:phrase, +P:phrase(A), X:list(A))// is nondet
- seqmap_with_sep(+S:phrase, +P:phrase(A,B), X:list(A), Y:list(B))// is nondet
- seqmap_with_sep(+S:phrase, +P:phrase(A,B,C), X:list(A), Y:list(B), Z:list(C))// is nondet
- As seqmap//2.. but inserting the separator phrase S between each call to P.
NB: Fails for empty lists.
- See also
- - seqmap//2
- seqmap_ints(+P:phrase(integer), +I:integer, +J:integer)// is nondet
- Equivalent to
seqmap(P)
applied to the list of integers from I to J inclusive.
- See also
- - seqmap//2.
- seqmap_args(+P:phrase(integer), +I:integer, +J:integer, X:term)// is nondet
- seqmap_args(+P:phrase(integer), +I:integer, +J:integer, X:term, Y:term)// is nondet
- seqmap_args(+P:phrase(integer), +I:integer, +J:integer, X:term, Y:term, Z:term)// is nondet
- Like seqmap//N, but applied to the arguments of term X, Y and Z, from the I th to the
J th inclusive.
- See also
- - seqmap//2.
- setof(Template:X, Phrase:phrase(S), Results:list(X), S1:S, S2:S) is nondet
- findall(Template:X, Phrase:phrase(S), Results:list(X), S1:S, S2:S) is nondet
- out(?X)// is det
- Equivalent to [X]. prepends X to the difference list represented by
the DCG state variables.
- list(?L)// is nondet
- Matches or outputs a sequence of nonterminals.
Undocumented predicates
The following predicates are exported, but not or incorrectly documented.
- \+(Arg1, Arg2, Arg3)
- forall(Arg1, Arg2, Arg3, Arg4)
- if(Arg1, Arg2, Arg3, Arg4)
- do_then_call(Arg1, Arg2, Arg3, Arg4, Arg5)
- do_then_call(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)
- do_then_call(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- lift(Arg1, Arg2, Arg3)
- lift(Arg1, Arg2, Arg3, Arg4)
- lift(Arg1, Arg2, Arg3, Arg4, Arg5)
- parmap(Arg1, Arg2, Arg3, Arg4)
- parmap(Arg1, Arg2, Arg3, Arg4, Arg5)
- parmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)
- parmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- parmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)
- seqmap(Arg1, Arg2, Arg3, Arg4, Arg5)
- seqmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)
- seqmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- seqmap(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)
- seqmap_n(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)
- seqmap_n(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- seqmap_with_sep(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)
- seqmap_with_sep(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- seqmap_args(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)
- seqmap_args(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)