**flag**(

`+Key, -Old, +New`)

`Old`is the current value of the flag

`Key`and the flag has been set to

`New`.

`New`can be an arithmetic expression. The update is

*atomic*. This predicate can be used to create a

*shared*global counter as illustrated in the example below.

next_id(Id) :- flag(my_id, Id, Id+1).

### 4.13.4 Tries

Tries (also called *digital tree*, *radix tree* or
*prefix tree* maintain a mapping between a variant of a term (see
=@=/2) and a value. They
have been introduced in SWI-Prolog 7.3.21 as part of the implementation
of *tabling*. The current implementation is rather immature. In
particular, the following limitations currently apply:

- Tries are not thread-safe.
- Tries should not be modified while non-deterministic predicates such as trie_gen/3 are running on the trie.
- Terms cannot have
*attributed variables*. - Terms cannot be
*cyclic*. Possibly this will not change because cyclic terms can only be supported after creating a canonical form of the term.

**We give the definition of these predicates for reference and
debugging tabled predicates. Future versions are likely to get a more
stable and safer implementation. The API to tries should not be
considered stable.**

**trie_new**(`-Trie`)- Create a new trie and unify
`Trie`with a handle to the trie. The trie handle is a*blob*. Tries are subject to atom garbage collection. **trie_destroy**(`+Trie`)- Destroy
`Trie`. This removes all nodes from the trie and causes further access to`Trie`to raise an existence_error exception. The handle itself is reclaimed by atom garbage collection. - [semidet]
**is_trie**(`@Trie`) - True when
`Trie`is a trie object. See also current_trie/1. - [nondet]
**current_trie**(`-Trie`) - True if
`Trie`is a currently existing trie. As this enumerates and then filters all known atoms this predicate is slow and should only be used for debugging purposes. See also is_trie/1. **trie_insert**(`+Trie, +Key`)- Insert the term
`Key`into`Trie`. If`Key`is already part of`Trie`the predicates*fails*silently. This is the same as trie_insert/3, but using a fixed reserved`Value`. **trie_insert**(`+Trie, +Key, +Value`)- Insert the term
`Key`into`Trie`and associate it with`Value`.`Value`can be any term. If`Key`-`Value`is already part of`Trie`, the predicates*fails*silently. If`Key`is in`Trie`associated with a different value, a`permission_error`

is raised. **trie_update**(`+Trie, +Key, +Value`)- As trie_insert/3,
but if
`Key`is in`Trie`, its associated value is*updated*. **trie_insert**(`+Trie, +Term, +Value, -Handle`)- As trie_insert/3,
returning a handle to the trie node. This predicate is currently unsafe
as
`Handle`is an integer used to encode a pointer. It was used to implement a pure Prolog version of the`library(tabling)`

library. **trie_delete**(`+Trie, +Key, ?Value`)- Delete
`Key`from`Trie`if the value associated with`Key`unifies with`Value`. **trie_lookup**(`+Trie, +Key, -Value`)- True if the term
`Key`is in`Trie`and associated with`Value`. **trie_term**(`+Handle, -Term`)- True when
`Term`is a copy of the term associated with`Handle`. The result is undefined (including crashes) if`Handle`is not a handle returned by trie_insert_new/3 or the node has been removed afterwards. - [nondet]
**trie_gen**(`+Trie, ?Key`) - True when
`Key`is a member of`Trie`. See also trie_gen_compiled/2. - [nondet]
**trie_gen**(`+Trie, ?Key, -Value`) - True when
`Key`is associated with`Value`in`Trie`. Backtracking retrieves all pairs. Currently scans the entire trie, even if`Key`is partly known. Currently unsafe if`Trie`is modified while the values are being enumerated. See also trie_gen_compiled/3. - [nondet]
**trie_gen_compiled**(`+Trie, ?Key`) - [nondet]
**trie_gen_compiled**(`+Trie, ?Key, -Value`) - Similar to trie_gen/3,
but uses a
*compiled*representation of`Trie`. The compiled representation is created lazily and manipulations of the trie (insert, delete) invalidate the current compiled representation. The compiled representation generates answers faster and, as it runs on a snapshot of the trie, is immune to concurrent modifications of the trie. This predicate is used to generate answers from*answer tries*as used for tabled execution. See section 7. - [nondet]
**trie_property**(`?Trie, ?Property`) - True if
`Trie`exists with`Property`. Intended for debugging and statistical purposes. Retrieving some of these properties visit all nodes of the trie. Defined properties are**value_count**(`-Count`)- Number of key-value pairs in the trie.
**node_count**(`-Count`)- Number of nodes in the trie.
**size**(`-Bytes`)- Required storage space of the trie.
**compiled_size**(`-Bytes`)- Required storage space for the compiled representation as used by trie_gen_compiled/2,3.
**hashed**(`-Count`)- Number of nodes that use a hashed index to its children.
**lookup_count**(`-Count`)- Number of trie_lookup/3
calls (only when compiled with
`O_TRIE_STATS`

). **gen_call_count**(`-Count`)- Number of trie_gen/3
calls (only when compiled with
`O_TRIE_STATS`

). **wait**(`-Count`)- Number of times a thread waited on this trie for another thread to
complete it (shared tabling, only when compiled with
`O_TRIE_STATS`

). **deadlock**(`-Count`)- Number of times this trie was part of a deadlock and its completion was
abandoned (shared tabling, only when compiled with
`O_TRIE_STATS`

).

In addition, a number of additional properties are defined on

*answer tries*.**invalidated**(`-Count`)- Number of times the trie was invalidated (incremental tabling).
**reevaluated**(`-Count`)- Number of times the trie was re-evaluated (incremental tabling).
**idg_affected_count**(`-Count`)- Number of answer tries affected by this one (incremental tabling).
**idg_dependent_count**(`-Count`)- Number of answer tries this one depends on (incremental tabling).
**idg_size**(`-Bytes`)- Number of bytes in the IDG node representation.

### 4.13.5 Update view

Traditionally,
Prolog systems used the *immediate update view*: new clauses
became visible to predicates backtracking over dynamic predicates
immediately, and retracted clauses became invisible immediately.

Starting with SWI-Prolog 3.3.0 we adhere to the *logical update
view*, where backtrackable predicates that enter the definition of a
predicate will not see any changes (either caused by assert/1
or
retract/1)
to the predicate. This view is the ISO standard, the most commonly used
and the most‘safe'.^{83For
example, using the immediate update view, no call to a dynamic predicate
is deterministic.} Logical updates are realised by keeping
reference counts on predicates and *generation* information on
clauses. Each change to the database causes an increment of the
generation of the database. Each goal is tagged with the generation in
which it was started. Each clause is flagged with the generation it was
created in as well as the generation it was erased from. Only clauses
with a‘created' ...‘erased' interval that encloses the
generation of the current goal are considered visible.

### 4.13.6 Indexing databases

The indexing capabilities of
SWI-Prolog are described in
section 2.18.
Summarizing, SWI-Prolog creates indexes for any applicable argument,
pairs of arguments and indexes on the arguments of compound terms when
applicable. Extended JIT indexing is not widely supported among Prolog
implementations. Programs that aim at portability should consider using term_hash/2
and term_hash/4
to design their database such that indexing on constant or functor
(name/arity reference) on the first argument is sufficient. In some
cases, using the predicates below to add one or more additional columns
(arguments) to a database predicate may improve performance. The overall
design of code using these predicates is given below. Note that as term_hash/2
leaves the hash unbound if `Term` is not ground. This causes
the lookup to be fast if `Term` is ground and correct (but
slow) otherwise.

:- dynamic x/2. assert_x(Term) :- term_hash(Term, Hash), assertz(x(Hash, Term)). x(Term) :- term_hash(Term, Hash), x(Hash, Term).

- [det]
**term_hash**(`+Term, -HashKey`) - If
`Term`is a ground term (see ground/1),`HashKey`is unified with a positive integer value that may be used as a hash key to the value. If`Term`is not ground, the predicate leaves`HashKey`an unbound variable. Hash keys are in the range`0 ... 16,777,215`, the maximal integer that can be stored efficiently on both 32 and 64 bit platforms.This predicate may be used to build hash tables as well as to exploit argument indexing to find complex terms more quickly.

The hash key does not rely on temporary information like addresses of atoms and may be assumed constant over different invocations and versions of SWI-Prolog.

^{84Last change: version 5.10.4}Hashes differ between big and little endian machines. The term_hash/2 predicate is cycle-safe.^{bugAll arguments that (indirectly) lead to a cycle have the same hash key.} - [det]
**term_hash**(`+Term, +Depth, +Range, -HashKey`) - As term_hash/2,
but only considers
`Term`to the specified`Depth`. The top-level term has depth 1, its arguments have depth 2, etc. That is,hashes nothing;`Depth`= 0hashes atomic values or the functor and arity of a compound term, not its arguments;`Depth`= 1also indexes the immediate arguments, etc.`Depth`= 2`HashKey`is in the range`[0 ...`.`Range`-1]`Range`must be in the range`[1 ... 2147483647]`. - [det]
**variant_sha1**(`+Term, -SHA1`) - Compute a SHA1-hash from
`Term`. The hash is represented as a 40-byte hexadecimal atom. Unlike term_hash/2 and friends, this predicate produces a hash key for non-ground terms. The hash is invariant over variable-renaming (see =@=/2) and constants over different invocations of Prolog.^{bugThe hash depends on word order (big/little-endian) and the wordsize (32/64 bits).}This predicate raises an exception when trying to compute the hash on a cyclic term or attributed term. Attributed terms are not handled because subsumes_chk/2 is not considered well defined for attributed terms. Cyclic terms are not supported because this would require establishing a canonical cycle. That is, given A=[a|A] and B=[a,a|B],

`A`and`B`should produce the same hash. This is not (yet) implemented.This hash was developed for lookup of solutions to a goal stored in a table. By using a cryptographic hash, heuristic algorithms can often ignore the possibility of hash collisions and thus avoid storing the goal term itself as well as testing using =@=/2.

- [det]
**variant_hash**(`+Term, -HashKey`) - Similar to variant_sha1/2,
but using a non-cryptographic hash and produces an integer result like term_hash/2.
This version does deal with attributed variables, processing them as
normal variables. This hash is primarily intended to speedup finding
variant terms in a set of terms.
^{bugAs variant_sha1/2, cyclic terms result in an exception.}