Transformation functions are pure (= side-effect free) functions or methods which can be used in queries to transform values and bind their results to pattern variables. Say, for example, there exists an attribute :person/born with type :db.type/instant. Given the birthday, it's easy to calculate the (very approximate) age of a person:
(defn age [birthday today]
(quot (- (.getTime today)
(.getTime birthday))
(* 1000 60 60 24 365)))with this function, we can now calculate the age of a person inside the query itself:
[:find ?age
:in $ ?name ?today
:where
[?p :person/name ?name]
[?p :person/born ?born]
[(tutorial.fns/age ?born ?today) ?age]]A transformation function clause has the shape [(<fn> <arg1> <arg2> ...) <result-binding>] where <result-binding> can be the same binding forms as we saw in chapter 3:
?age[?foo ?bar ?baz][?name ...][[?title ?rating]]One thing to be aware of is that transformation functions can't be nested. You can't write
[(f (g ?x)) ?a]instead, you must bind intermediate results in temporary pattern variables
[(g ?x) ?t]
[(f ?t) ?a]Find people by age. Use the function tutorial.fns/age to find the age given a birthday and a date representing "today".
The birthday paradox states that in a room of 23 people there is a 50% chance that someone has the same birthday. Write a query to find who has the same birthday. Use the < predicate on the names to avoid duplicate answers. You can use (the deprecated) .getDate and .getMonth java Date methods.
Query:[ I give up! ]