clementine 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README.md +52 -0
- data/Rakefile +1 -0
- data/clementine.gemspec +23 -0
- data/lib/clementine.rb +27 -0
- data/lib/clementine/clementine_rails.rb +8 -0
- data/lib/clementine/clojurescript_engine.rb +49 -0
- data/lib/clementine/clojurescript_engine_mri.rb +65 -0
- data/lib/clementine/clojurescript_template.rb +21 -0
- data/lib/clementine/options.rb +9 -0
- data/lib/clementine/version.rb +3 -0
- data/test/clojurescript_engine_test.rb +46 -0
- data/test/options_test.rb +22 -0
- data/vendor/assets/bin/cljsc.clj +21 -0
- data/vendor/assets/lib/clojure.jar +0 -0
- data/vendor/assets/lib/compiler.jar +0 -0
- data/vendor/assets/lib/goog.jar +0 -0
- data/vendor/assets/lib/js.jar +0 -0
- data/vendor/assets/src/clj/cljs/closure.clj +823 -0
- data/vendor/assets/src/clj/cljs/compiler.clj +1341 -0
- data/vendor/assets/src/clj/cljs/core.clj +702 -0
- data/vendor/assets/src/clj/cljs/repl.clj +162 -0
- data/vendor/assets/src/clj/cljs/repl/browser.clj +341 -0
- data/vendor/assets/src/clj/cljs/repl/rhino.clj +170 -0
- data/vendor/assets/src/cljs/cljs/core.cljs +3330 -0
- data/vendor/assets/src/cljs/cljs/nodejs.cljs +11 -0
- data/vendor/assets/src/cljs/cljs/nodejs_externs.js +2 -0
- data/vendor/assets/src/cljs/cljs/nodejscli.cljs +9 -0
- data/vendor/assets/src/cljs/cljs/reader.cljs +360 -0
- data/vendor/assets/src/cljs/clojure/browser/dom.cljs +106 -0
- data/vendor/assets/src/cljs/clojure/browser/event.cljs +100 -0
- data/vendor/assets/src/cljs/clojure/browser/net.cljs +182 -0
- data/vendor/assets/src/cljs/clojure/browser/repl.cljs +109 -0
- data/vendor/assets/src/cljs/clojure/set.cljs +162 -0
- data/vendor/assets/src/cljs/clojure/string.cljs +160 -0
- data/vendor/assets/src/cljs/clojure/walk.cljs +94 -0
- data/vendor/assets/src/cljs/clojure/zip.cljs +291 -0
- metadata +103 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
;; Copyright (c) Rich Hickey. All rights reserved.
|
2
|
+
;; The use and distribution terms for this software are covered by the
|
3
|
+
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
4
|
+
;; which can be found in the file epl-v10.html at the root of this distribution.
|
5
|
+
;; By using this software in any fashion, you are agreeing to be bound by
|
6
|
+
;; the terms of this license.
|
7
|
+
;; You must not remove this notice, or any other, from this software.
|
8
|
+
|
9
|
+
(ns ^{:doc "This namespace contains functions to work with browser
|
10
|
+
events. It is based on the Google Closure Library event system."
|
11
|
+
:author "Bobby Calderwood"}
|
12
|
+
clojure.browser.event
|
13
|
+
(:require [goog.events :as events]
|
14
|
+
[goog.events.EventTarget :as gevent-target]
|
15
|
+
[goog.events.EventType :as gevent-type]))
|
16
|
+
|
17
|
+
(defprotocol EventType
|
18
|
+
(event-types [this]))
|
19
|
+
|
20
|
+
(extend-protocol EventType
|
21
|
+
|
22
|
+
goog.events.EventTarget
|
23
|
+
(event-types
|
24
|
+
[this]
|
25
|
+
(into {}
|
26
|
+
(map
|
27
|
+
(fn [[k v]]
|
28
|
+
[(keyword (. k (toLowerCase)))
|
29
|
+
v])
|
30
|
+
(merge
|
31
|
+
(js->clj goog.events.EventType)))))
|
32
|
+
|
33
|
+
js/Element
|
34
|
+
(event-types
|
35
|
+
[this]
|
36
|
+
(into {}
|
37
|
+
(map
|
38
|
+
(fn [[k v]]
|
39
|
+
[(keyword (. k (toLowerCase)))
|
40
|
+
v])
|
41
|
+
(merge
|
42
|
+
(js->clj goog.events.EventType))))))
|
43
|
+
|
44
|
+
(defn listen
|
45
|
+
([src type fn]
|
46
|
+
(listen src type fn false))
|
47
|
+
([src type fn capture?]
|
48
|
+
(goog.events/listen src
|
49
|
+
(get (event-types src) type type)
|
50
|
+
fn
|
51
|
+
capture?)))
|
52
|
+
|
53
|
+
(defn listen-once
|
54
|
+
([src type fn]
|
55
|
+
(listen-once src type fn false))
|
56
|
+
([src type fn capture?]
|
57
|
+
(goog.events/listenOnce src
|
58
|
+
(get (event-types src) type type)
|
59
|
+
fn
|
60
|
+
capture?)))
|
61
|
+
|
62
|
+
(defn unlisten
|
63
|
+
([src type fn]
|
64
|
+
(unlisten src type fn false))
|
65
|
+
([src type fn capture?]
|
66
|
+
(goog.events/unlisten src
|
67
|
+
(get (event-types src) type type)
|
68
|
+
fn
|
69
|
+
capture?)))
|
70
|
+
|
71
|
+
(defn unlisten-by-key
|
72
|
+
[key]
|
73
|
+
(goog.events/unlistenByKey key))
|
74
|
+
|
75
|
+
(defn dispatch-event
|
76
|
+
[src event]
|
77
|
+
(goog.events/dispatchEvent src event))
|
78
|
+
|
79
|
+
(defn expose [e]
|
80
|
+
(goog.events/expose e))
|
81
|
+
|
82
|
+
(defn fire-listeners
|
83
|
+
[obj type capture event])
|
84
|
+
|
85
|
+
(defn total-listener-count []
|
86
|
+
(goog.events/getTotalListenerCount))
|
87
|
+
|
88
|
+
;; TODO
|
89
|
+
(defn get-listener [src type listener opt_capt opt_handler]); ⇒ ?Listener
|
90
|
+
(defn all-listeners [obj type capture]); ⇒ Array.<Listener>
|
91
|
+
|
92
|
+
(defn unique-event-id [event-type]); ⇒ string
|
93
|
+
|
94
|
+
(defn has-listener [obj opt_type opt_capture]); ⇒ boolean
|
95
|
+
;; TODO? (defn listen-with-wrapper [src wrapper listener opt_capt opt_handler])
|
96
|
+
;; TODO? (defn protect-browser-event-entry-point [errorHandler])
|
97
|
+
|
98
|
+
(defn remove-all [opt_obj opt_type opt_capt]); ⇒ number
|
99
|
+
;; TODO? (defn unlisten-with-wrapper [src wrapper listener opt_capt opt_handler])
|
100
|
+
|
@@ -0,0 +1,182 @@
|
|
1
|
+
;; Copyright (c) Rich Hickey. All rights reserved.
|
2
|
+
;; The use and distribution terms for this software are covered by the
|
3
|
+
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
4
|
+
;; which can be found in the file epl-v10.html at the root of this distribution.
|
5
|
+
;; By using this software in any fashion, you are agreeing to be bound by
|
6
|
+
;; the terms of this license.
|
7
|
+
;; You must not remove this notice, or any other, from this software.
|
8
|
+
|
9
|
+
(ns ^{:doc "Network communication library, wrapping goog.net.
|
10
|
+
Includes a common API over XhrIo, CrossPageChannel, and Websockets."
|
11
|
+
:author "Bobby Calderwood and Alex Redington"}
|
12
|
+
clojure.browser.net
|
13
|
+
(:require [clojure.browser.event :as event]
|
14
|
+
[goog.net.XhrIo :as gxhrio]
|
15
|
+
[goog.net.EventType :as gnet-event-type]
|
16
|
+
[goog.net.xpc.CfgFields :as gxpc-config-fields]
|
17
|
+
[goog.net.xpc.CrossPageChannel :as xpc]
|
18
|
+
#_[goog.net.WebSocket :as gwebsocket]
|
19
|
+
[goog.json :as gjson]))
|
20
|
+
|
21
|
+
(def *timeout* 10000)
|
22
|
+
|
23
|
+
(def event-types
|
24
|
+
(into {}
|
25
|
+
(map
|
26
|
+
(fn [[k v]]
|
27
|
+
[(keyword (. k (toLowerCase)))
|
28
|
+
v])
|
29
|
+
(merge
|
30
|
+
(js->clj goog.net.EventType)))))
|
31
|
+
|
32
|
+
(defprotocol IConnection
|
33
|
+
(connect
|
34
|
+
[this]
|
35
|
+
[this opt1]
|
36
|
+
[this opt1 opt2]
|
37
|
+
[this opt1 opt2 opt3])
|
38
|
+
(transmit
|
39
|
+
[this opt]
|
40
|
+
[this opt opt2]
|
41
|
+
[this opt opt2 opt3]
|
42
|
+
[this opt opt2 opt3 opt4]
|
43
|
+
[this opt opt2 opt3 opt4 opt5])
|
44
|
+
(close [this]))
|
45
|
+
|
46
|
+
(extend-type goog.net.XhrIo
|
47
|
+
|
48
|
+
IConnection
|
49
|
+
(transmit
|
50
|
+
([this uri]
|
51
|
+
(transmit this uri "GET" nil nil *timeout*))
|
52
|
+
([this uri method]
|
53
|
+
(transmit this uri method nil nil *timeout*))
|
54
|
+
([this uri method content]
|
55
|
+
(transmit this uri method content nil *timeout*))
|
56
|
+
([this uri method content headers]
|
57
|
+
(transmit this uri method content headers *timeout*))
|
58
|
+
([this uri method content headers timeout]
|
59
|
+
(.setTimeoutInterval this timeout)
|
60
|
+
(.send this uri method content headers)))
|
61
|
+
|
62
|
+
|
63
|
+
event/EventType
|
64
|
+
(event-types [this]
|
65
|
+
(into {}
|
66
|
+
(map
|
67
|
+
(fn [[k v]]
|
68
|
+
[(keyword (. k (toLowerCase)))
|
69
|
+
v])
|
70
|
+
(merge
|
71
|
+
(js->clj goog.net.EventType))))))
|
72
|
+
|
73
|
+
;; TODO jQuery/sinatra/RestClient style API: (get [uri]), (post [uri payload]), (put [uri payload]), (delete [uri])
|
74
|
+
|
75
|
+
(def xpc-config-fields
|
76
|
+
(into {}
|
77
|
+
(map
|
78
|
+
(fn [[k v]]
|
79
|
+
[(keyword (. k (toLowerCase)))
|
80
|
+
v])
|
81
|
+
(js->clj goog.net.xpc.CfgFields))))
|
82
|
+
|
83
|
+
(defn xhr-connection
|
84
|
+
"Returns an XhrIo connection"
|
85
|
+
[]
|
86
|
+
(goog.net.XhrIo.))
|
87
|
+
|
88
|
+
(defprotocol ICrossPageChannel
|
89
|
+
(register-service [this service-name fn] [this service-name fn encode-json?]))
|
90
|
+
|
91
|
+
(extend-type goog.net.xpc.CrossPageChannel
|
92
|
+
|
93
|
+
ICrossPageChannel
|
94
|
+
(register-service
|
95
|
+
([this service-name fn]
|
96
|
+
(register-service this service-name fn false))
|
97
|
+
([this service-name fn encode-json?]
|
98
|
+
(.registerService this (name service-name) fn encode-json?)))
|
99
|
+
|
100
|
+
IConnection
|
101
|
+
(connect
|
102
|
+
([this]
|
103
|
+
(connect this nil))
|
104
|
+
([this on-connect-fn]
|
105
|
+
(.connect this on-connect-fn))
|
106
|
+
([this on-connect-fn config-iframe-fn]
|
107
|
+
(connect this on-connect-fn config-iframe-fn (.body js/document)))
|
108
|
+
([this on-connect-fn config-iframe-fn iframe-parent]
|
109
|
+
(.createPeerIframe this iframe-parent config-iframe-fn)
|
110
|
+
(.connect this on-connect-fn)))
|
111
|
+
|
112
|
+
(transmit [this service-name payload]
|
113
|
+
(.send this (name service-name) payload))
|
114
|
+
|
115
|
+
(close [this]
|
116
|
+
(.close this ())))
|
117
|
+
|
118
|
+
(defn xpc-connection
|
119
|
+
"When passed with a config hash-map, returns a parent
|
120
|
+
CrossPageChannel object. Keys in the config hash map are downcased
|
121
|
+
versions of the goog.net.xpc.CfgFields enum keys,
|
122
|
+
e.g. goog.net.xpc.CfgFields.PEER_URI becomes :peer_uri in the config
|
123
|
+
hash.
|
124
|
+
|
125
|
+
When passed with no args, creates a child CrossPageChannel object,
|
126
|
+
and the config is automatically taken from the URL param 'xpc', as
|
127
|
+
per the CrossPageChannel API."
|
128
|
+
([]
|
129
|
+
(when-let [config (.getParameterValue
|
130
|
+
(goog.Uri. (.href (.location js/window)))
|
131
|
+
"xpc")]
|
132
|
+
(goog.net.xpc.CrossPageChannel. (gjson/parse config))))
|
133
|
+
([config]
|
134
|
+
(goog.net.xpc.CrossPageChannel.
|
135
|
+
(.strobj (reduce (fn [sum [k v]]
|
136
|
+
(when-let [field (get xpc-config-fields k)]
|
137
|
+
(assoc sum field v)))
|
138
|
+
{}
|
139
|
+
config)))))
|
140
|
+
|
141
|
+
;; WebSocket is not supported in the 3/23/11 release of Google
|
142
|
+
;; Closure, but will be included in the next release.
|
143
|
+
|
144
|
+
#_(defprotocol IWebSocket
|
145
|
+
(open? [this]))
|
146
|
+
|
147
|
+
#_(extend-type goog.net.WebSocket
|
148
|
+
|
149
|
+
IWebSocket
|
150
|
+
(open? [this]
|
151
|
+
(.isOpen this ()))
|
152
|
+
|
153
|
+
IConnection
|
154
|
+
(connect
|
155
|
+
([this url]
|
156
|
+
(connect this url nil))
|
157
|
+
([this url protocol]
|
158
|
+
(.open this url protocol)))
|
159
|
+
|
160
|
+
(transmit [this message]
|
161
|
+
(.send this message))
|
162
|
+
|
163
|
+
(close [this]
|
164
|
+
(.close this ()))
|
165
|
+
|
166
|
+
event/EventType
|
167
|
+
(event-types [this]
|
168
|
+
(into {}
|
169
|
+
(map
|
170
|
+
(fn [[k v]]
|
171
|
+
[(keyword (. k (toLowerCase)))
|
172
|
+
v])
|
173
|
+
(merge
|
174
|
+
(js->clj goog.net.WebSocket/EventType))))))
|
175
|
+
|
176
|
+
#_(defn websocket-connection
|
177
|
+
([]
|
178
|
+
(websocket-connection nil nil))
|
179
|
+
([auto-reconnect?]
|
180
|
+
(websocket-connection auto-reconnect? nil))
|
181
|
+
([auto-reconnect? next-reconnect-fn]
|
182
|
+
(goog.net.WebSocket. auto-reconnect? next-reconnect-fn)))
|
@@ -0,0 +1,109 @@
|
|
1
|
+
;; Copyright (c) Rich Hickey. All rights reserved.
|
2
|
+
;; The use and distribution terms for this software are covered by the
|
3
|
+
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
4
|
+
;; which can be found in the file epl-v10.html at the root of this distribution.
|
5
|
+
;; By using this software in any fashion, you are agreeing to be bound by
|
6
|
+
;; the terms of this license.
|
7
|
+
;; You must not remove this notice, or any other, from this software.
|
8
|
+
|
9
|
+
(ns ^{:doc "Receive - Eval - Print - Loop
|
10
|
+
|
11
|
+
Receive a block of JS (presumably generated by a ClojureScript compiler)
|
12
|
+
Evaluate it naively
|
13
|
+
Print the result of evaluation to a string
|
14
|
+
Send the resulting string back to the server Loop!"
|
15
|
+
|
16
|
+
:author "Bobby Calderwood and Alex Redington"}
|
17
|
+
clojure.browser.repl
|
18
|
+
(:require [clojure.browser.net :as net]
|
19
|
+
[clojure.browser.event :as event]))
|
20
|
+
|
21
|
+
(def xpc-connection (atom nil))
|
22
|
+
|
23
|
+
(defn repl-print [data]
|
24
|
+
(if-let [conn @xpc-connection]
|
25
|
+
(net/transmit conn :print (pr-str data))))
|
26
|
+
|
27
|
+
(defn evaluate-javascript
|
28
|
+
"Process a single block of JavaScript received from the server"
|
29
|
+
[conn block]
|
30
|
+
(let [result (try {:status :success :value (str (js* "eval(~{block})"))}
|
31
|
+
(catch js/Error e
|
32
|
+
{:status :exception :value (pr-str e)
|
33
|
+
:stacktrace (if (.hasOwnProperty e "stack")
|
34
|
+
(.stack e)
|
35
|
+
"No stacktrace available.")}))]
|
36
|
+
(pr-str result)))
|
37
|
+
|
38
|
+
(defn send-result [connection url data]
|
39
|
+
(net/transmit connection url "POST" data nil 0))
|
40
|
+
|
41
|
+
(defn send-print
|
42
|
+
"Send data to be printed in the REPL. If there is an error, try again
|
43
|
+
up to 10 times."
|
44
|
+
([url data]
|
45
|
+
(send-print url data 0))
|
46
|
+
([url data n]
|
47
|
+
(let [conn (net/xhr-connection)]
|
48
|
+
(event/listen conn :error
|
49
|
+
(fn [_]
|
50
|
+
(if (< n 10)
|
51
|
+
(send-print url data (inc n))
|
52
|
+
(.log js/console (str "Could not send " data " after " n " attempts.")))))
|
53
|
+
(net/transmit conn url "POST" data nil 0))))
|
54
|
+
|
55
|
+
(def order (atom 0))
|
56
|
+
|
57
|
+
(defn wrap-message [t data]
|
58
|
+
(pr-str {:type t :content data :order (swap! order inc)}))
|
59
|
+
|
60
|
+
(defn start-evaluator
|
61
|
+
"Start the REPL server connection."
|
62
|
+
[url]
|
63
|
+
(if-let [repl-connection (net/xpc-connection)]
|
64
|
+
(let [connection (net/xhr-connection)]
|
65
|
+
(event/listen connection
|
66
|
+
:success
|
67
|
+
(fn [e]
|
68
|
+
(net/transmit
|
69
|
+
repl-connection
|
70
|
+
:evaluate-javascript
|
71
|
+
(.getResponseText e/currentTarget
|
72
|
+
()))))
|
73
|
+
|
74
|
+
(net/register-service repl-connection
|
75
|
+
:send-result
|
76
|
+
(fn [data]
|
77
|
+
(send-result connection url (wrap-message :result data))))
|
78
|
+
|
79
|
+
(net/register-service repl-connection
|
80
|
+
:print
|
81
|
+
(fn [data]
|
82
|
+
(send-print url (wrap-message :print data))))
|
83
|
+
|
84
|
+
(net/connect repl-connection
|
85
|
+
(constantly nil))
|
86
|
+
|
87
|
+
(js/setTimeout #(send-result connection url (wrap-message :ready "ready")) 50))
|
88
|
+
(js/alert "No 'xpc' param provided to child iframe.")))
|
89
|
+
|
90
|
+
(defn connect
|
91
|
+
"Connects to a REPL server from an HTML document. After the
|
92
|
+
connection is made, the REPL will evaluate forms in the context of
|
93
|
+
the document that called this function."
|
94
|
+
[repl-server-url]
|
95
|
+
(let [repl-connection (net/xpc-connection
|
96
|
+
{:peer_uri repl-server-url})]
|
97
|
+
(swap! xpc-connection (constantly repl-connection))
|
98
|
+
(net/register-service repl-connection
|
99
|
+
:evaluate-javascript
|
100
|
+
(fn [js]
|
101
|
+
(net/transmit
|
102
|
+
repl-connection
|
103
|
+
:send-result
|
104
|
+
(evaluate-javascript repl-connection js))))
|
105
|
+
(net/connect repl-connection
|
106
|
+
(constantly nil)
|
107
|
+
(fn [iframe]
|
108
|
+
(set! iframe.style.display
|
109
|
+
"none")))))
|
@@ -0,0 +1,162 @@
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
2
|
+
; The use and distribution terms for this software are covered by the
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
6
|
+
; the terms of this license.
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
8
|
+
|
9
|
+
(ns ^{:doc "Set operations such as union/intersection."
|
10
|
+
:author "Rich Hickey"}
|
11
|
+
clojure.set)
|
12
|
+
|
13
|
+
(defn- bubble-max-key [k coll]
|
14
|
+
"Move a maximal element of coll according to fn k (which returns a number)
|
15
|
+
to the front of coll."
|
16
|
+
(let [max (apply max-key k coll)]
|
17
|
+
(cons max (remove #(identical? max %) coll))))
|
18
|
+
|
19
|
+
(defn union
|
20
|
+
"Return a set that is the union of the input sets"
|
21
|
+
([] #{})
|
22
|
+
([s1] s1)
|
23
|
+
([s1 s2]
|
24
|
+
(if (< (count s1) (count s2))
|
25
|
+
(reduce conj s2 s1)
|
26
|
+
(reduce conj s1 s2)))
|
27
|
+
([s1 s2 & sets]
|
28
|
+
(let [bubbled-sets (bubble-max-key count (conj sets s2 s1))]
|
29
|
+
(reduce into (first bubbled-sets) (rest bubbled-sets)))))
|
30
|
+
|
31
|
+
(defn intersection
|
32
|
+
"Return a set that is the intersection of the input sets"
|
33
|
+
([s1] s1)
|
34
|
+
([s1 s2]
|
35
|
+
(if (< (count s2) (count s1))
|
36
|
+
(recur s2 s1)
|
37
|
+
(reduce (fn [result item]
|
38
|
+
(if (contains? s2 item)
|
39
|
+
result
|
40
|
+
(disj result item)))
|
41
|
+
s1 s1)))
|
42
|
+
([s1 s2 & sets]
|
43
|
+
(let [bubbled-sets (bubble-max-key #(- (count %)) (conj sets s2 s1))]
|
44
|
+
(reduce intersection (first bubbled-sets) (rest bubbled-sets)))))
|
45
|
+
|
46
|
+
(defn difference
|
47
|
+
"Return a set that is the first set without elements of the remaining sets"
|
48
|
+
([s1] s1)
|
49
|
+
([s1 s2]
|
50
|
+
(if (< (count s1) (count s2))
|
51
|
+
(reduce (fn [result item]
|
52
|
+
(if (contains? s2 item)
|
53
|
+
(disj result item)
|
54
|
+
result))
|
55
|
+
s1 s1)
|
56
|
+
(reduce disj s1 s2)))
|
57
|
+
([s1 s2 & sets]
|
58
|
+
(reduce difference s1 (conj sets s2))))
|
59
|
+
|
60
|
+
|
61
|
+
(defn select
|
62
|
+
"Returns a set of the elements for which pred is true"
|
63
|
+
[pred xset]
|
64
|
+
(reduce (fn [s k] (if (pred k) s (disj s k)))
|
65
|
+
xset xset))
|
66
|
+
|
67
|
+
(defn project
|
68
|
+
"Returns a rel of the elements of xrel with only the keys in ks"
|
69
|
+
[xrel ks]
|
70
|
+
(set (map #(select-keys % ks) xrel)))
|
71
|
+
|
72
|
+
(defn rename-keys
|
73
|
+
"Returns the map with the keys in kmap renamed to the vals in kmap"
|
74
|
+
[map kmap]
|
75
|
+
(reduce
|
76
|
+
(fn [m [old new]]
|
77
|
+
(if (and (not= old new)
|
78
|
+
(contains? m old))
|
79
|
+
(-> m (assoc new (get m old)) (dissoc old))
|
80
|
+
m))
|
81
|
+
map kmap))
|
82
|
+
|
83
|
+
(defn rename
|
84
|
+
"Returns a rel of the maps in xrel with the keys in kmap renamed to the vals in kmap"
|
85
|
+
[xrel kmap]
|
86
|
+
(set (map #(rename-keys % kmap) xrel)))
|
87
|
+
|
88
|
+
(defn index
|
89
|
+
"Returns a map of the distinct values of ks in the xrel mapped to a
|
90
|
+
set of the maps in xrel with the corresponding values of ks."
|
91
|
+
[xrel ks]
|
92
|
+
(reduce
|
93
|
+
(fn [m x]
|
94
|
+
(let [ik (select-keys x ks)]
|
95
|
+
(assoc m ik (conj (get m ik #{}) x))))
|
96
|
+
{} xrel))
|
97
|
+
|
98
|
+
(defn map-invert
|
99
|
+
"Returns the map with the vals mapped to the keys."
|
100
|
+
[m] (reduce (fn [m [k v]] (assoc m v k)) {} m))
|
101
|
+
|
102
|
+
(defn join
|
103
|
+
"When passed 2 rels, returns the rel corresponding to the natural
|
104
|
+
join. When passed an additional keymap, joins on the corresponding
|
105
|
+
keys."
|
106
|
+
([xrel yrel] ;natural join
|
107
|
+
(if (and (seq xrel) (seq yrel))
|
108
|
+
(let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel))))
|
109
|
+
[r s] (if (<= (count xrel) (count yrel))
|
110
|
+
[xrel yrel]
|
111
|
+
[yrel xrel])
|
112
|
+
idx (index r ks)]
|
113
|
+
(reduce (fn [ret x]
|
114
|
+
(let [found (idx (select-keys x ks))]
|
115
|
+
(if found
|
116
|
+
(reduce #(conj %1 (merge %2 x)) ret found)
|
117
|
+
ret)))
|
118
|
+
#{} s))
|
119
|
+
#{}))
|
120
|
+
([xrel yrel km] ;arbitrary key mapping
|
121
|
+
(let [[r s k] (if (<= (count xrel) (count yrel))
|
122
|
+
[xrel yrel (map-invert km)]
|
123
|
+
[yrel xrel km])
|
124
|
+
idx (index r (vals k))]
|
125
|
+
(reduce (fn [ret x]
|
126
|
+
(let [found (idx (rename-keys (select-keys x (keys k)) k))]
|
127
|
+
(if found
|
128
|
+
(reduce #(conj %1 (merge %2 x)) ret found)
|
129
|
+
ret)))
|
130
|
+
#{} s))))
|
131
|
+
|
132
|
+
(defn subset?
|
133
|
+
"Is set1 a subset of set2?"
|
134
|
+
[set1 set2]
|
135
|
+
(and (<= (count set1) (count set2))
|
136
|
+
(every? #(contains? set2 %) set1)))
|
137
|
+
|
138
|
+
(defn superset?
|
139
|
+
"Is set1 a superset of set2?"
|
140
|
+
[set1 set2]
|
141
|
+
(and (>= (count set1) (count set2))
|
142
|
+
(every? #(contains? set1 %) set2)))
|
143
|
+
|
144
|
+
(comment
|
145
|
+
(refer 'set)
|
146
|
+
(def xs #{{:a 11 :b 1 :c 1 :d 4}
|
147
|
+
{:a 2 :b 12 :c 2 :d 6}
|
148
|
+
{:a 3 :b 3 :c 3 :d 8 :f 42}})
|
149
|
+
|
150
|
+
(def ys #{{:a 11 :b 11 :c 11 :e 5}
|
151
|
+
{:a 12 :b 11 :c 12 :e 3}
|
152
|
+
{:a 3 :b 3 :c 3 :e 7 }})
|
153
|
+
|
154
|
+
(join xs ys)
|
155
|
+
(join xs (rename ys {:b :yb :c :yc}) {:a :a})
|
156
|
+
|
157
|
+
(union #{:a :b :c} #{:c :d :e })
|
158
|
+
(difference #{:a :b :c} #{:c :d :e})
|
159
|
+
(intersection #{:a :b :c} #{:c :d :e})
|
160
|
+
|
161
|
+
(index ys [:b]))
|
162
|
+
|