Just pushed a powerful new feature to Cascalog today called "predicate
macros". Don't let the name scare you off, they're really easy to use!
Predicate macros allow you to arbitrarily compose together other
predicates. Predicate macros are defined when input or output vars are
explicitly defined using :> or :< within the declared variables of a
When a predicate macro is used, it expands to one or more predicates.
For example, here's the how you can compose together "sum" and "count"
to create "average":
(def average (<- [!val :> !avg] (c/count !c) (c/sum !val :> !s) (div !
s !c :> !avg)))
Here's an example of how average is expanded within a query:
(<- [?avg-age] (age _ ?a) (average ?a :> ?avg-age))
(<- [?avg-age] (age _ ?a) (count !c_1) (sum ?a :> !s_1) (div !s_1 !
c_1 :> ?avg-age))
Any non-declared variables used in a predicate macro, like !s and !c
in average, are given unique names so as not to conflict with other
variables when expanded.
Another example of a predicate macro is "distinct count", which will
count the number of unique occurrences of a value. distinct-count
secondary sorts the values and then does the computation in a single
scan of the values through a custom aggregator:
(def distinct-count (<- [!v :> !c] (:sort !v) (distinct-count-agg !
v :> !c)))