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.