4.21 Analysing and Constructing Terms
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Built-in Predicates
        • Analysing and Constructing Terms
          • functor/3
          • functor/4
          • arg/3
          • =../2
          • compound_name_arity/3
          • compound_name_arguments/3
          • numbervars/3
          • numbervars/4
          • var_number/2
          • term_variables/2
          • nonground/2
          • term_variables/3
          • term_singletons/2
          • is_most_general_term/1
          • copy_term/2
          • copy_term/4
          • copy_term_nat/4
          • Non-logical operations on terms
            • setarg/3
            • nb_setarg/3
            • nb_linkarg/3
            • duplicate_term/2
            • same_term/2
    • Packages

4.21.1 Non-logical operations on terms

Prolog is not able to modify instantiated parts of a term. Lacking that capability makes the language much safer, but unfortunately there are problems that suffer severely in terms of time and/or memory usage. Always try hard to avoid the use of these primitives, but they can be a good alternative to using dynamic predicates. See also section 4.33, discussing the use of global variables.

setarg(+Arg, +Term, +Value)
Extra-logical predicate. Assigns the Arg-th argument of the compound term Term with the given Value. The assignment is undone if backtracking brings the state back into a position before the setarg/3 call. If the designated argument of Term is a variable, this variable is unified with Value using normal unification, i.e., setarg/3 behaves as arg/3 in this case. Note that this may produce a cyclic term if Value contains this variable. See also nb_setarg/3.

This predicate may be used for destructive assignment to terms, using them as an extra-logical storage bin. Always try hard to avoid the use of setarg/3 as it is not supported by many Prolog systems and one has to be very careful about unexpected copying as well as unexpected noncopying of terms. A good practice to improve somewhat on this situation is to make sure that terms whose arguments are subject to setarg/3 have one unused and unshared variable in addition to the used arguments. This variable avoids unwanted sharing in, e.g., copy_term/2, and causes the term to be considered as non-ground. An alternative is to use put_attr/3 to attach information to attributed variables (seeĀ section 8.1).

nb_setarg(+Arg, +Term, +Value)
Assigns the Arg-th argument of the compound term Term with the given Value as setarg/3, but on backtracking the assignment is not reversed. If Value is not atomic, it is duplicated using duplicate_term/2. This predicate uses the same technique as nb_setval/2. We therefore refer to the description of nb_setval/2 for details on non-backtrackable assignment of terms. This predicate is compatible with GNU-Prolog setarg(A,T,V,false), removing the type restriction on Value. See also nb_linkarg/3. Below is an example for counting the number of solutions of a goal. Note that this implementation is thread-safe, reentrant and capable of handling exceptions. Realising these features with a traditional implementation based on assert/retract or flag/3 is much more complicated.
:- meta_predicate
        succeeds_n_times(0, -).

succeeds_n_times(Goal, Times) :-
        Counter = counter(0),
        (   Goal,
            arg(1, Counter, N0),
            N is N0 + 1,
            nb_setarg(1, Counter, N),
            fail
        ;   arg(1, Counter, Times)
        ).
nb_linkarg(+Arg, +Term, +Value)
As nb_setarg/3, but like nb_linkval/2 it does not duplicate Value. Use with extreme care and consult the documentation of nb_linkval/2 before use.
duplicate_term(+In, -Out)
Version of copy_term/2 that also copies ground terms and therefore ensures that destructive modification using setarg/3 does not affect the copy. See also nb_setval/2, nb_linkval/2, nb_setarg/3 and nb_linkarg/3.
[semidet]same_term(@T1, @T2)
True if T1 and T2 are equivalent and will remain equivalent, even if setarg/3 is used on either of them. This means T1 and T2 are the same variable, equivalent atomic data or a compound term allocated at the same address.