library(arg)
library(arg)
defines seven predicates, all of which are generalizations
of the built-in predicate arg/3
.
arg(
+ArgNum,
+Term,
-Arg)
arg/3
signals an error. Basically, arg/3
pretends to be the
infinite table
arg(1, a(X), X). arg(1, a(X,_), X). arg(2, a(_,X), X). ... arg(5, zebra_finch(_,_,_,_,X,_,_,_), X). ...
except that it can only be used to
find the Arg for a given Index and Term, and cannot
find the Index. arg/3
is a built-in predicate, and is described
in the reference pages, not
actually defined in library(arg)
.
arg0(
+Index,
+Term,
?Arg)
Index > 0
, or with the principal function symbol of
Term if
Index = 0
. This predicate is supplied because
some other Prolog implementations have
made arg/3
do this, and this makes it easier to convert
code originally written for those systems.
The one reason you might use arg0/3
is that it
reports errors, while arg/3
, for backwards compatibility
with DEC-10 Prolog, does not. Examples:
| ?- arg0(2, f(o,x,y), X). X = x | ?- arg0(0, f(o,x,y), X). X = f | ?- arg0(N, f(o,x,y), X). ! Instantiation error in argument 1 of arg0/3 ! goal: arg0(_732,f(o,x,y),_767) | ?- arg0(y, f(o,x,y), N). ! Type error in argument 1 of arg0/3 ! integer expected, but y found ! goal: arg0(y,f(o,x,y),_764)
genarg(
?Index,
+Term,
?Arg)
arg/3
that is able to solve for
Index as well as for Arg.
| ?- arg(N, f(a,b), X). no | ?- genarg(N, f(a,b), X). N = 2, X = b ; N = 1, X = a ; no
| ?- genarg(N, f(1,b,2), X), atom(X). N = 2, X = b ; no | ?- genarg(3, f(1,b,2), X). X = 2
If Index is instantiated, genarg/3
generates the same result as
arg/3
.
If Index is uninstantiated, genarg/3
picks out each argument in turn.
The order in which the arguments are tried is not defined;
the current implementation works from right to left, but this order should
not be relied upon.
genarg0(
?Index,
+Term,
?Arg)
arg0/3
that is able to solve for Index as well as
Arg.
args(
?Index,
+Terms,
?Args)
arg(
Index,
Term,
Arg)
is
true for
each pair <
Term,
Arg>
of corresponding elements of
<
Terms,
Args>
.
Index is strictly positive, and only arguments are found, not
principal function symbols. This is a generalization of genarg/3
. For
example,
| ?- args(1, [a+b,c-d,e*f,g/h], X). X = [a,c,e,g] | ?- args(2, [a+A,c-B,e*C,g/D], [b,d,f,h]). A = b, B = d, C = f, D = h
| ?- args(I, [1-a,2-b,3-c,4-d], X). I = 2, X = [a,b,c,d] ; I = 1, X = [1,2,3,4]
args0(
?Index,
+Terms,
?Args)
args/3
except that
Index = 0
selects the principal
function symbol.
| ?- args0(0, [a+b,c-d,e*f,g/h,27], X). X = [+,-,*,/,27] | ?- args0(I, [1-a,2-b,3-c,4-d], X). I = 2, X = [a,b,c,d] ; I = 1, X = [1,2,3,4] ; I = 0, X = [-,-,-,-]
This is a generalization of genarg0/3
.
project(
+Terms,
?Index,
?Args)
args0/3
except for the argument
order. The argument order of project/3
is not
consistent with anything else in the library. This
predicate is retained for backwards compatibility.
Use args0/3
instead in new programs.
path_arg(
?Path,
+Term,
?SubTerm)
path_arg([I,J], MyTerm, MySubTerm)
unifies MySubTerm
with the J
'th argument of the I
'th argument of MyTerm
.
In general, Term should be ground.
path_arg/3
may be regarded as a generalization of genarg/3
.
It can be used to find the SubTerm and a known Path, or to
find a Path to a known SubTerm. It could have been defined
as
path_arg([], Term, Term). path_arg([Index|Indices], Term, SubTerm) :- genarg(Index, Term, Arg), path_arg(Indices, Arg, SubTerm).
The actual library program is rather more complicated because it contains error-reporting code. Examples of its use include:
/* Here is a sample table of all the subterms of /* the quadratic formula "(a*x^2) + (b*x) + c = 0" /* [] a*x^2+b*x+c=0 [1] a*x^2+b*x+c [1,1] a*x^2+b*x [1,1,1] a*x^2 [1,1,1,1] a [1,1,1,2] x^2 [1,1,1,2,1] x [1,1,1,2,2] 2 [1,1,2] b*x [1,1,2,1] b [1,1,2,2] x [1,2] c [2] 0 */ | ?- path_arg([1,1,2,2], a*x^2+b*x+c=0, X). X = x ^
| ?- path_arg([1,1,1,2,2], a*x^2+b*x+c=0, X). X = 2 ^ | ?- path_arg(Path, a*x^2+b*x+c=0, b). Path = [1,1,2,1] ^
This notation for locating subtrees of a tree is widely used throughout computer science.
Note that except for project/3
, which is included only in the
interests of backwards compatibility, all of these predicates
have the same pattern of arguments:
For consistency, we recommend that you use this argument order for "selector" predicates generally: first the argument or arguments that constitute the selector or index, then the thing or things that are being selected from, and finally the result or results.