Term processing

### 8.4 Term processing

- `functor/3`
- `arg/3`
- `(=..)/2` - univ
- `copy_term/2`
- `term_variables/2`, `term_variables/3`
- `subsumes_term/2`
- `acyclic_term/1`
- `term_hash/4`, `term_hash/2`
- `setarg/4`, `setarg/3`

#### 8.4.1 `functor/3`

Templates

  `functor(+nonvar, ?atomic, ?integer)
  functor(-nonvar, +atomic, +integer)`

Description

`functor(Term, Name, Arity)` succeeds if the principal functor of `Term` is `Name` and its arity is `Arity`. This predicate can be used in two ways:

- `Term` is not a variable: extract the name (an atom or a number if `Term` is a number) and the arity of `Term` (if `Term` is atomic `Arity` = 0).
- `Term` is a variable: unify `Term` with a general term whose principal functor is given by `Name` and arity is given by `Arity`.

Errors

`Term` and `Name` are both variables |  | `instantiation_error`
`Term` and `Arity` are both variables |  | `instantiation_error`
`Term` is a variable and `Name` is neither a variable nor an atomic term |  | `type_error(atomic, Name)`
`Term` is a variable and `Arity` is neither a variable nor an integer |  | `type_error(integer, Arity)`
`Term` is a variable, `Name` is a constant but not an atom and `Arity` is an integer > 0 |  | `type_error(atom, Name)`
`Term` is a variable and `Arity` is an integer > `max_arity` flag (section 8.22.1) |  | `representation_error(max_arity)`
`Term` is a variable and `Arity` is an integer < 0 |  | `domain_error(not_less_than_zero, Arity)`

Portability

ISO predicate.

#### 8.4.2 `arg/3`

Templates

  `arg(+integer, +compound_term, ?term)`

Description

`arg(N, Term, Arg)` succeeds if the `N`th argument of `Term` is `Arg`.

Errors

`N` is a variable |  | `instantiation_error`
`Term` is a variable |  | `instantiation_error`
`N` is neither a variable nor an integer |  | `type_error(integer, N)`
`Term` is neither a variable nor a compound term |  | `type_error(compound, Term)`
`N` is an integer < 0 |  | `domain_error(not_less_than_zero, N)`

Portability

ISO predicate.

#### 8.4.3 `(=..)/2` - univ

Templates

  `=..(+nonvar, ?list)
  =..(-nonvar, +list)`

Description

`Term =.. List` succeeds if `List` is a list whose head is the atom corresponding to the principal functor of `Term` and whose tail is a list of the arguments of `Term`.

`=..` is a predefined infix operator (section 8.14.10).

Errors

`Term` is a variable and `List` is a partial list |  | `instantiation_error`
`List` is neither a partial list nor a list |  | `type_error(list, List)`
`Term` is a variable and `List` is a list whose head is a variable |  | `instantiation_error`
`List` is a list whose head `H` is neither an atom nor a variable and whose tail is not the empty list |  | `type_error(atom, H)`
`List` is a list whose head `H` is a compound term and whose tail is the empty list |  | `type_error(atomic, H)`
`Term` is a variable and `List` is the empty list |  | `domain_error(non_empty_list, [])`
`Term` is a variable and the tail of `List` has a length > `max_arity` flag (section 8.22.1) |  | `representation_error(max_arity)`

Portability

ISO predicate.

#### 8.4.4 `copy_term/2`

Templates

  `copy_term(?term, ?term)`

Description

`copy_term(Term1, Term2)` succeeds if `Term2` unifies with a term `T` which is a renamed copy of `Term1`.

Errors

None.

Portability

ISO predicate.

#### 8.4.5 `term_variables/2`, `term_variables/3`

Templates

  `term_variables(?term, ?list)
  term_variables(?term, ?list, ?list)
  `

Description

`term_variables(Term, List)` succeeds if `List` unifies with a list of variables (including FD variables), each sharing with a unique variable of `Term`. The variables in `List` are ordered in order of appearance traversing `Term` depth-first and left-to-right.

`term_variables(Term, List, Tail)` is a difference-list version of the above predicate, i.e. `Tail` is the tail of the variable-list `List`.

Errors

in `term_variables/2` `List` is neither a partial list nor a list |  | `type_error(list, List)`

Portability

`term_variables/2` is an ISO Predicate. `term_variables/3` is a GNU Prolog predicate.

#### 8.4.6 `subsumes_term/2`

Templates

  `subsumes_term(?term, ?term)`

Description

`subsumes_term(General, Specific)` succeeds if `General` can be made equivalent to `Specific` by binding variables in `General` leaving `Specific` unaffected. The current implementation performs the unification (with occurs check) and ensures that the variable set of `Specific` is not changed by the unification (which is then undone). Note that this predicate fails in the presence of FD variables in `Specific`.

Errors

None.

Portability

ISO predicate.

#### 8.4.7 `acyclic_term/1`

Templates

  `acyclic_term(?term)`

Description

`acyclic_term(Term)` succeeds if `Term` does not contain a cyclic (sub-)term. In this case, Term may be processed safely. If `acyclic_term(Term)` fails, `Term` contains a cycle and processing Term is not safe, because GNU Prolog does not support the unification of cyclic terms but permits their creation. Cycles can be safely undone by failing over their creation. The use of `acyclic_term/1` shall thus be reserved to protect critical predicates against cyclic terms.

Errors

None.

Portability

ISO predicate.

#### 8.4.8 `term_hash/4`, `term_hash/2`

Templates

  `term_hash(?term, +integer, +integer, ?integer)
  term_hash(?term, ?integer)`

Description

`term_hash(Term, Depth, Range, Hash)` succeeds if `Hash` is the hash code of `Term`. If `Term` is not ground (see `ground/1` (section 8.1.1)), the predicate simply succeeds (`Hash` is not unified). `Depth` is the depth limit to scan `Term` (starting from 1 for the top-level term). With `Depth` = 0 nothing is hashed, with 1 only atomic terms and the main functors/arity are hashed,... With `Depth` = -1 the full term is considered.

The hash code is as follows: 0 ≤ `Hash` < `Range`. If `Range` = 0 then `Hash` is not restricted (currently it is < 268435456).

`term_hash(Term, Hash)` is equivalent to `term_hash(Term, -1, 0, Hash)`.

NB: the computed hash code is independent of any runtime context (i.e. it is constant across different executions). It is also independent on the underlying machine.

These predicates are useful to implement hash tables or argument indexing.

Errors

`Depth` is a variable |  | `instantiation_error`
`Depth` is neither a variable nor an integer |  | `type_error(integer, Depth)`
`Range` is a variable |  | `instantiation_error`
`Range` is neither a variable nor an integer |  | `type_error(integer, Range)`
`Range` is an integer < 0 |  | `domain_error(not_less_than_zero, Range)`
`Hash` is neither a variable nor an integer |  | `type_error(integer, Hash)`

Portability

GNU Prolog predicate.

#### 8.4.9 `setarg/4`, `setarg/3`

Templates

  `setarg(+integer, +compound_term, +term, +boolean)
  setarg(+integer, +compound_term, +term)`

Description

`setarg(N, Term, NewValue, Undo)` replaces destructively the `N`th argument of `Term` with `NewValue`. This assignment is undone on backtracking if `Undo` = `true`. This should only used if there is no further use of the old value of the replaced argument. If `Undo` = `false` then `NewValue` must be either an atom or an integer.

`setarg(N, Term, NewValue)` is equivalent to `setarg(N, Term, NewValue, true)`.

Errors

`N` is a variable |  | `instantiation_error`
`N` is neither a variable nor an integer |  | `type_error(integer, N)`
`N` is an integer < 0 |  | `domain_error(not_less_than_zero, N)`
`Term` is a variable |  | `instantiation_error`
`Term` is neither a variable nor a compound term |  | `type_error(compound, Term)`
`NewValue` is neither an atom nor an integer and `Undo` = `false` |  | `type_error(atomic, NewValue)`
`Undo` is a variable |  | `instantiation_error`
`Undo` is neither a variable nor a boolean |  | `type_error(boolean, Undo)`

Portability

GNU Prolog predicate.

Copyright (C) 1999-2012 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright