Skip to content

Instantly share code, notes, and snippets.

@sritchie
Created January 25, 2012 09:46
Show Gist options
  • Save sritchie/1675672 to your computer and use it in GitHub Desktop.
Save sritchie/1675672 to your computer and use it in GitHub Desktop.
(defn chain
"Accepts a sequence of operations (beginning with a generator) and
threads each tuple through each of the operators in turn, returning
the final set of tuples."
[& ops]
(let [[ret :as vars] (v/gen-nullable-vars (count ops))]
(construct [ret]
(map (fn [op [out-var in-var]]
(if in-var
[op in-var :> out-var]
[op out-var]))
(reverse ops)
(partition-all 2 1 vars)))))
user> (??- (chain [[1] [2] [3]] #'inc))
;;=> (([2] [3] [4]))
user> (??- (chain [[1] [2] [3]] #'inc #'inc))
;;=> (([3] [4] [5]))
user> (defn square [x] (* x x))
;;=> #'backtype.lyoto.conversion.spiderduck/square
user> (??- (chain [[1] [2] [3]] #'inc #'square #'inc))
;;=> (([5] [10] [17]))
;; This last chain expands out into:
;;
;; (let [src [[1] [2] [3]]]
;; (<- [?out]
;; (src ?a)
;; (inc ?a :> ?b)
;; (square ?b :> ?c)
;; (inc ?c :> ?out)))
;;
;; Slightly different version w/ no distincting:
(defn chain
"Accepts a sequence of operations (beginning with a generator) and
threads each tuple through each of the operators in turn, returning
the final set of tuples."
[& ops]
(let [[ret :as vars] (v/gen-nullable-vars (count ops))
preds (-> (map (fn [op [out-var in-var]]
(if in-var
[op in-var :> out-var]
[op out-var]))
(reverse ops)
(partition-all 2 1 vars))
(conj [:distinct false]))]
(construct [ret] preds)))
;; Very similar to cascalog.ops/comp:
(defn comp
"Accepts any number of predicate ops and returns an op that is the
composition of those ops.
(require '[cascalog.ops :as c])
((c/comp #'str #'+) ?x ?y :> ?sum-string) ;; within some query
Is equivalent to:
;; within some query
(+ ?x ?y :> ?intermediate)
(str ?intermediate :> ?sum-string)"
[& ops]
(let [[invar & more] (v/gen-nullable-vars (inc (clojure.core/count ops)))
allvars (list* invar (map vector more))]
(construct [:<< invar :> (last more)]
(map (fn [o [invars outvars]]
[o :<< invars :>> outvars])
(reverse ops)
(partition 2 1 allvars)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment