5.4.1 Functions on dicts
The infix operator dot (op(100, yfx, .)
is used to
extract values and evaluate functions on dicts. Functions are recognised
if they appear in the argument of a goal in the source text,
possibly nested in a term. The keys act as field selector, which is
illustrated in this example.
?- X = point{x:1,y:2}.x. X = 1. ?- Pt = point{x:1,y:2}, write(Pt.y). 2 Pt = point{x:1,y:2}. ?- X = point{x:1,y:2}.C. X = 1, C = x ; X = 2, C = y.
The compiler translates a goal that contains
terms in its arguments into a conjunction of calls to ./3
defined in the
.
/2system
module. Terms functor.
2 that appears in
the head are replaced with a variable and calls to ./3
are inserted at the start of the body. Below are two examples, where the
first extracts the
x
key from a dict and the second extends a dict containing
an address with the postal code, given a find_postal_code/4 predicate.
dict_x(X, X.x). add_postal_code(Dict, Dict.put(postal_code, Code)) :- find_postal_code(Dict.city, Dict.street, Dict.house_number, Code).
Note that expansion of
terms implies
that such terms cannot be created by writing them explicitly in your
source code. Such terms can still be created with functor/3, =../2,
compound_name_arity/3
and
compound_name_arguments/3.178Traditional
code is unlikely to use .
/2
terms because they
were practically reserved for usage in lists. We do not provide a
quoting mechanism as found in functional languages because it would only
be needed to quote .
/2
terms, such terms are
rare and term manipulation provides an escape route.
.
/2
- .(+Dict, +Function, -Result)
- This predicate is called to evaluate
terms found in the arguments of a goal. This predicate evaluates the field extraction described above, raising an exception if Function is an atom (key) and Dict does not contain the requested key. If Function is a compound term, it checks for the predefined functions on dicts described in section 5.4.1.2 or executes a user defined function as described in section 5.4.1.1..
/2
5.4.1.1 User defined functions on dicts
The tag of a dict associates the dict to a module. If the dot notation uses a compound term, this calls the goal below.
<module>:<name>(Arg1, ..., +Dict, -Value)
Functions are normal Prolog predicates. The dict infrastructure
provides a more convenient syntax for representing the head of such
predicates without worrying about the argument calling conventions. The
code below defines a function multiply(Times)
on a point
that creates a new point by multiplying both coordinates. and len
179as length
would result in a predicate length/2,
this name cannot be used. This might change in future versions.
to compute the length from the origin. The . and :=
operators are used to abstract the location of the predicate arguments.
It is allowed to define multiple a function with multiple clauses,
providing overloading and non-determinism.
:- module(point, []). M.multiply(F) := point{x:X, y:Y} :- X is M.x*F, Y is M.y*F. M.len() := Len :- Len is sqrt(M.x**2 + M.y**2).
After these definitions, we can evaluate the following functions:
?- X = point{x:1, y:2}.multiply(2). X = point{x:2, y:4}. ?- X = point{x:1, y:2}.multiply(2).len(). X = 4.47213595499958.
5.4.1.2 Predefined functions on dicts
Dicts currently define the following reserved functions:
- get(?KeyPath)
- Return the value associates with KeyPath. KeyPath
is either a single key or a term
Key1/Key2/...
. Each key is either an atom, small integer or a variable. WhileDict.Key
throws an existence error, this function fails silently if a key does not exist in the target dict. See also :</2, which can be used to test for existence and unify multiple key values from a dict. For example:?- write(t{a:x}.get(a)). x ?- write(t{a:x}.get(b)). false. ?- write(t{a:t{b:x}}.get(a/b)). x
- put(+New)
- Evaluates to a new dict where the key-values in New replace or extend the key-values in the original dict. See put_dict/3.
- get(?KeyPath, +Default)
- Same as get/1 , but if no match is found the function evaluates to Default. If KeyPath contains variables possible choice points are respected and the function only evaluates to Default if the pattern has no matches.
- put(+KeyPath, +Value)
- Evaluates to a new dict where the KeyPath-Value
replaces or extends the key-values in the original dict. KeyPath
is either a key or a term KeyPath/Key,180Note
that we do not use the’.’functor here, because the
would evaluate. replacing the value associated with Key in a sub-dict of the dict on which the function operates. See put_dict/4. Below are some examples:.
/2?- A = _{}.put(a, 1). A = _G7359{a:1}. ?- A = _{a:1}.put(a, 2). A = _G7377{a:2}. ?- A = _{a:1}.put(b/c, 2). A = _G1395{a:1, b:_G1584{c:2}}. ?- A = _{a:_{b:1}}.put(a/b, 2). A = _G1429{a:_G1425{b:2}}. ?- A = _{a:1}.put(a/b, 2). A = _G1395{a:_G1578{b:2}}.