5.4.2 Predicates for managing dicts
This section documents the predicates that are defined on dicts. We
use the naming and argument conventions of the traditional library(assoc)
.
- is_dict(@Term)
- True if Term is a dict. This is the same as
is_dict(Term,_)
. - is_dict(@Term, -Tag)
- True if Term is a dict of Tag.
- get_dict(?Key, +Dict, -Value)
- Unify the value associated with Key in dict with Value.
If
Key is unbound, all associations in Dict are
returned on backtracking. The order in which the associations are
returned is undefined. This predicate is normally accessed using the
functional notation
Dict.Key
. See section 5.4.1. - [semidet]get_dict(+Key, +Dict, -Value, -NewDict, +NewValue)
- Create a new dict after updating the value for Key. Fails if
Value does not unify with the current value associated with
Key. Acts according to the following below. Dict
is either a dict or a list the can be converted into a dict.
get_dict(Key, Dict, Value, NewDict, NewDict) :- get_dict(Key, Dict, Value), put_dict(Key, Dict, NewDict, NewDict).
- dict_create(-Dict, +Tag, +Data)
- Create a dict in Tag from Data. Data is
a list of attribute-value pairs using the syntax
Key:Value
,Key=Value
,Key-Value
orKey(Value)
. An exception is raised if Data is not a proper list, one of the elements is not of the shape above, a key is neither an atom nor a small integer or there is a duplicate key. - dict_pairs(?Dict, ?Tag, ?Pairs)
- Bi-directional mapping between a dict and an ordered list of pairs (see section A.22).
- put_dict(+New, +DictIn, -DictOut)
- DictOut is a new dict created by replacing or adding
key-value pairs from New to Dict. New
is either a dict or a valid input for dict_create/3.
This predicate is normally accessed using the functional notation. Below
are some examples:
?- A = point{x:1, y:2}.put(_{x:3}). A = point{x:3, y:2}. ?- A = point{x:1, y:2}.put([x=3]). A = point{x:3, y:2}. ?- A = point{x:1, y:2}.put([x=3,z=0]). A = point{x:3, y:2, z:0}.
- put_dict(+Key, +DictIn, +Value, -DictOut)
- DictOut is a new dict created by replacing or adding
Key-Value to DictIn. This predicate is
normally accessed using the functional notation. Below is an example:
?- A = point{x:1, y:2}.put(x, 3). A = point{x:3, y:2}.
- del_dict(+Key, +DictIn, ?Value, -DictOut)
- True when Key-Value is in DictIn and DictOut contains all associations of DictIn except for Key.
- [semidet]+Select :< +From
- True when Select is a `sub dict' of From: the
tages must unify and all keys in Select must appear with
unifying values in From. From may contain keys
that are not in
Select. This operation is frequently used to match a
dict and at the same time extract relevant values from it. For example:
plot(Dict, On) :- _{x:X, y:Y, z:Z} :< Dict, !, plot_xyz(X, Y, Z, On). plot(Dict, On) :- _{x:X, y:Y} :< Dict, !, plot_xy(X, Y, On).
The goal
Select :< From
is equivalent toselect_dict(Select, From, _)
. - [semidet]select_dict(+Select, +From, -Rest)
- True when the tags of Select and From have been
unified, all keys in Select appear in From and the
corresponding values have been unified. The key-value pairs of From
that do not appear in Select are used to form an anonymous
dict, which us unified with Rest. For example:
?- select_dict(P{x:0, y:Y}, point{x:0, y:1, z:2}, R). P = point, Y = 1, R = _G1705{z:2}.
See also select_dict/2 to ignore Rest and >:</2 for a symmetric partial unification of two dicts.
- +Dict1 >:< +Dict2
- This operator specifies a partial unification between
Dict1 and Dict2. It is true when the tags and the
values associated with all common keys have been unified. The
values associated to keys that do not appear in the other dict are
ignored. Partial unification is symmetric. For example, given a list of
dicts, find dicts that represent a point with X equal to zero:
member(Dict, List), Dict >:< point{x:0, y:Y}.
See also :</2 and select_dict/3.
5.4.2.1 Destructive assignment in dicts
This section describes the destructive update operations defined on
dicts. These actions can only update keys and not add or remove
keys. If the requested key does not exist the predicate raises
existence_error(key, Key, Dict)
. Note the additional
argument.
Destructive assignment is a non-logical operation and should be used with care because the system may copy or share identical Prolog terms at any time. Some of this behaviour can be avoided by adding an additional unbound value to the dict. This prevents unwanted sharing and ensures that copy_term/2 actually copies the dict. This pitfall is demonstrated in the example below:
?- A = a{a:1}, copy_term(A,B), b_set_dict(a, A, 2). A = B, B = a{a:2}. ?- A = a{a:1,dummy:_}, copy_term(A,B), b_set_dict(a, A, 2). A = a{a:2, dummy:_G3195}, B = a{a:1, dummy:_G3391}.
- [det]b_set_dict(+Key, !Dict, +Value)
- Destructively update the value associated with Key in Dict to Value. The update is trailed and undone on backtracking. This predicate raises an existence error if Key does not appear in Dict. The update semantics are equivalent to setarg/3 and b_setval/2.
- [det]nb_set_dict(+Key, !Dict, +Value)
- Destructively update the value associated with Key in Dict to a copy of Value. The update is not undone on backtracking. This predicate raises an existence error if Key does not appear in Dict. The update semantics are equivalent to nb_setarg/3 and nb_setval/2.
- [det]nb_link_dict(+Key, !Dict, +Value)
- Destructively update the value associated with Key in Dict to Value. The update is not undone on backtracking. This predicate raises an existence error if Key does not appear in Dict. The update semantics are equivalent to nb_linkarg/3 and nb_linkval/2. Use with extreme care and consult the documentation of nb_linkval/2 before use.