rlm@10
|
1 ;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
|
rlm@10
|
2 ;; distribution terms for this software are covered by the Eclipse Public
|
rlm@10
|
3 ;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can
|
rlm@10
|
4 ;; be found in the file epl-v10.html at the root of this distribution. By
|
rlm@10
|
5 ;; using this software in any fashion, you are agreeing to be bound by the
|
rlm@10
|
6 ;; terms of this license. You must not remove this notice, or any other,
|
rlm@10
|
7 ;; from this software.
|
rlm@10
|
8 ;;
|
rlm@10
|
9 ;; util.clj
|
rlm@10
|
10 ;;
|
rlm@10
|
11 ;; A Clojure implementation of Datalog -- Utilities
|
rlm@10
|
12 ;;
|
rlm@10
|
13 ;; straszheimjeffrey (gmail)
|
rlm@10
|
14 ;; Created 3 Feburary 2009
|
rlm@10
|
15
|
rlm@10
|
16
|
rlm@10
|
17 (ns clojure.contrib.datalog.util
|
rlm@10
|
18 (:use [clojure.contrib.seq :only (separate)]))
|
rlm@10
|
19
|
rlm@10
|
20
|
rlm@10
|
21
|
rlm@10
|
22 ;;; Bindings and logic vars. A binding in a hash of logic vars to
|
rlm@10
|
23 ;;; bound values. Logic vars are any symbol prefixed with a \?.
|
rlm@10
|
24
|
rlm@10
|
25 (defn is-var?
|
rlm@10
|
26 "Is this a logic variable: e.g. a symbol prefixed with a ?"
|
rlm@10
|
27 [sym]
|
rlm@10
|
28 (when (symbol? sym)
|
rlm@10
|
29 (let [name (name sym)]
|
rlm@10
|
30 (and (= \? (first name))
|
rlm@10
|
31 (not= \? (fnext name))))))
|
rlm@10
|
32
|
rlm@10
|
33 (defn is-query-var?
|
rlm@10
|
34 "Is this a query variable: e.g. a symbol prefixed with ??"
|
rlm@10
|
35 [sym]
|
rlm@10
|
36 (when (symbol? sym)
|
rlm@10
|
37 (let [name (name sym)]
|
rlm@10
|
38 (and (= \? (first name))
|
rlm@10
|
39 (= \? (fnext name))))))
|
rlm@10
|
40
|
rlm@10
|
41 (defn map-values
|
rlm@10
|
42 "Like map, but works over the values of a hash map"
|
rlm@10
|
43 [f hash]
|
rlm@10
|
44 (let [key-vals (map (fn [[key val]] [key (f val)]) hash)]
|
rlm@10
|
45 (if (seq key-vals)
|
rlm@10
|
46 (apply conj (empty hash) key-vals)
|
rlm@10
|
47 hash)))
|
rlm@10
|
48
|
rlm@10
|
49 (defn keys-to-vals
|
rlm@10
|
50 "Given a map and a collection of keys, return the collection of vals"
|
rlm@10
|
51 [m ks]
|
rlm@10
|
52 (vals (select-keys m ks)))
|
rlm@10
|
53
|
rlm@10
|
54 (defn reverse-map
|
rlm@10
|
55 "Reverse the keys/values of a map"
|
rlm@10
|
56 [m]
|
rlm@10
|
57 (into {} (map (fn [[k v]] [v k]) m)))
|
rlm@10
|
58
|
rlm@10
|
59
|
rlm@10
|
60 ;;; Preduce -- A parallel reduce over hashes
|
rlm@10
|
61
|
rlm@10
|
62 (defn preduce
|
rlm@10
|
63 "Similar to merge-with, but the contents of each key are merged in
|
rlm@10
|
64 parallel using f.
|
rlm@10
|
65
|
rlm@10
|
66 f - a function of 2 arguments.
|
rlm@10
|
67 data - a collection of hashes."
|
rlm@10
|
68 [f data]
|
rlm@10
|
69 (let [data-1 (map (fn [h] (map-values #(list %) h)) data)
|
rlm@10
|
70 merged (doall (apply merge-with concat data-1))
|
rlm@10
|
71 ; Groups w/ multiple elements are identified for parallel processing
|
rlm@10
|
72 [complex simple] (separate (fn [[key vals]] (> (count vals) 1)) merged)
|
rlm@10
|
73 fold-group (fn [[key vals]] {key (reduce f vals)})
|
rlm@10
|
74 fix-single (fn [[key [val]]] [key val])]
|
rlm@10
|
75 (apply merge (concat (pmap fold-group merged) (map fix-single simple)))))
|
rlm@10
|
76
|
rlm@10
|
77
|
rlm@10
|
78 ;;; Debuging and Tracing
|
rlm@10
|
79
|
rlm@10
|
80 (def *trace-datalog* nil)
|
rlm@10
|
81
|
rlm@10
|
82 (defmacro trace-datalog
|
rlm@10
|
83 "If *test-datalog* is set to true, run the enclosed commands"
|
rlm@10
|
84 [& body]
|
rlm@10
|
85 `(when *trace-datalog*
|
rlm@10
|
86 ~@body))
|
rlm@10
|
87
|
rlm@10
|
88
|
rlm@10
|
89 ;; End of file
|