#### Finding a Term's Arguments -- `library(arg)`

`library(arg)` defines seven predicates, all of which are generalizations of the built-in predicate `arg/3`.

`arg(`+ArgNum`, `+Term`, `-Arg`)`
unifies Arg with the ArgNumth argument of Term. Term must not be a variable, but any other kind of term is acceptable. Even a number is acceptable as Term; numbers are simply terms that happen to have no arguments. ArgNum must be instantiated to an integer. If ArgNum is less than 1 or greater than the number of arguments of Term, `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`)`
unifies Arg with the Indexth argument of Term if 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`)`
is a version of `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`)`
is a version of `arg0/3` that is able to solve for Index as well as Arg.
`args(`?Index`, `+Terms`, `?Args`)`
is true when Terms and Args are lists of the same length, each element of Terms is instantiated to a term having at least Index arguments, and `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`)`
is like `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`)`
is identical to `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`)`
unifies SubTerm with the subterm of Term found by following Path, where Path is a sequence of positive integers. For example, the goal
```          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
         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
                     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:

• first Index (or its equivalent, Path)
• then Term (or Terms)
• and finally Arg (or Args)

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.