Skip to content

Commit 3eec718

Browse files
committed
2 parents 24cf797 + 056ba65 commit 3eec718

23 files changed

+1145
-399
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ pom.xml.asc
77
*.class
88
/.lein-*
99
/.nrepl-port
10+
/.cljs_rhino_repl
1011
*~

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The `active.clojure.record` namespace implements a
1212

1313
### Records (Spec)
1414

15-
The `active.clojure.record` namespace implements a
15+
The `active.clojure.record-spec` namespace implements a
1616
`define-record-type` form similar to Scheme's [SRFI
1717
9](http://srfi.schemers.org/srfi-9/) (similar to `active.clojure.record`).
1818

@@ -38,11 +38,13 @@ Example:
3838
```
3939

4040
This defines the following Specs (aside from what the regular
41-
`active.cloujre.record`s already define):
41+
`active.clojure.record`s already define):
4242

43-
* `::card` a Spec which conforms values that are instances of a card (see
43+
* `::card`, a Spec which conforms values that are instances of a card (see
4444
example below).
45-
* Specs for accessors.
45+
* Specs `::card-number` and `::card-color` for accessors. Note that these names
46+
are **not** based on the given accessor names but rather a concatenation of
47+
the record type and field names.
4648
* Spec for the constructor function.
4749

4850
```clojure
@@ -118,7 +120,7 @@ tools such as a macro `pret` that prints and returns its argument.
118120

119121
### Pattern Matching
120122

121-
The `active.clojure.match` namespaces provides some syntactic sugar
123+
The `active.clojure.match` namespace provides some syntactic sugar
122124
for map matching around `core.match`.
123125

124126
## License

project.clj

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
(defproject active-clojure "0.23.0-SNAPSHOT"
1+
(defproject active-clojure "0.27.0-SNAPSHOT"
22
:description "Active Clojure: Various Clojure utilities in use at Active Group"
33
:url "http://github.com/active-group/active-clojure"
44
:license {:name "Eclipse Public License"
55
:url "http://www.eclipse.org/legal/epl-v10.html"}
6-
:dependencies [[org.clojure/clojure "1.9.0-RC1"]
7-
[io.aviso/pretty "0.1.24"]
8-
[org.clojure/core.match "0.3.0-alpha4"]
6+
:dependencies [[org.clojure/clojure "1.9.0"]
7+
[io.aviso/pretty "0.1.34"]
8+
[org.clojure/core.match "0.3.0-alpha5"]
99
[org.clojure/test.check "0.10.0-alpha2"]]
1010

1111
:generated-paths ["target"]
12-
12+
1313
:clean-targets ^{:protect false} [:generated-paths]
1414

1515
:cljsbuild {:builds
@@ -22,17 +22,24 @@
2222
:compiler {:output-to "target/test.js"
2323
;; this fixes an error from doo
2424
:output-dir "target"
25-
:source-map "target/test.map"
2625
:main active.clojure.test-runner
27-
:optimizations :whitespace
26+
:optimizations :whitespace ;; This is required for testing with nashorn.
2827
:pretty-print true}}}}
2928

30-
:profiles {:dev {:dependencies [[lein-doo "0.1.6"]]}
31-
:cljs {:dependencies [[org.clojure/clojurescript "1.9.293"]]}}
29+
:profiles {:cljs {:dependencies [[org.clojure/clojurescript "1.10.238"]
30+
[com.cemerick/piggieback "0.2.2"]
31+
[org.clojure/tools.nrepl "0.2.10"]
32+
[doo "0.1.10"]]
33+
;; run CLJS repl with
34+
;; lein with-profile cljs repl
35+
;; (cemerick.piggieback/cljs-repl (cljs.repl.rhino/repl-env))
36+
:repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}}
3237

33-
:aliases {"test-nashorn" ["with-profile" "cljs" "doo" "nashorn" "test"]}
38+
:aliases {"test-nashorn" ["with-profile" "cljs" "doo" "nashorn" "test"]
39+
"test-phantom" ["with-profile" "cljs" "doo" "phantom" "test"]
40+
}
3441

35-
:plugins [[lein-cljsbuild "1.1.3"]
36-
[lein-doo "0.1.6"]]
42+
:plugins [[lein-cljsbuild "1.1.7"]
43+
[lein-doo "0.1.10"]]
3744

3845
:global-vars {*warn-on-reflection* true})

src/active/clojure/condition.cljc

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
(ns ^{:doc "Conditions, protocol for communicating the causes of exceptions.
1+
(ns active.clojure.condition
2+
"Conditions, protocol for communicating the causes of exceptions.
23
34
This provides infrastructure for building *condition* objects.
45
A condition object provides information about the cause of an exception.
@@ -12,9 +13,8 @@
1213
1314
Condition objects are represented as specially marked `ex-info` objects.
1415
15-
One notable difference to the R6RS design is that there is no user-facing type for
16-
'simple conditions', nor are they regular records."}
17-
active.clojure.condition
16+
One notable difference to the R6RS design is that there is no user-facing type for
17+
'simple conditions', nor are they regular records."
1818
(:refer-clojure :exclude (assert))
1919
#?(:clj (:require [clojure.core :as core] ; get assert back
2020
[clojure.stacktrace :as stack]
@@ -66,7 +66,7 @@
6666
(print-condition exc w)
6767
(.write w (str "clojure.lang.ExceptionInfo: " (.getMessage exc) " " (str (ex-data exc)))))))
6868

69-
(defn ^:private ex-info-msg
69+
(defn ^:private ex-info-msg
7070
[namespace]
7171
(str "This is a " namespace " active.clojure.condition."))
7272

@@ -376,7 +376,7 @@
376376
377377
For internal use."
378378
[?base ?who ?message ?irritants]
379-
`(let [g# (group-by (fn [thing#] (or (condition? thing#) (instance? Throwable thing#))) ~?irritants)
379+
`(let [g# (group-by (fn [thing#] (or (condition? thing#) (if-cljs (instance? js/Error thing#) (instance? Throwable thing#)))) ~?irritants)
380380
irritants# (get g# false)
381381
conditions# (get g# true)
382382
who# ~?who]
@@ -387,7 +387,7 @@
387387
(and (not-empty irritants#) (make-irritants-condition irritants#))
388388
conditions#)))))
389389

390-
(defn error
390+
(defn error
391391
"Throw an exception that signals that an error has occurred.
392392
393393
This function should be called when an error has occurred,
@@ -502,7 +502,7 @@
502502
"Return a keyword describing the type,
503503
a symbol or string describing the source of the problem, an error
504504
message or nil, and a sequence of other objects describing the
505-
problem.
505+
problem.
506506
507507
Valid type symbols include: `:error`, `:assertion-violation`,
508508
`:violation`, `:serious`."
@@ -625,4 +625,3 @@
625625
(print spaces)
626626
(pr irritant))
627627
(print "\n")))))
628-

src/active/clojure/config.cljc

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,25 @@ settings that can be mixed in, like so:
2424
2525
Each profile has the same format as the top-level configuration itself
2626
(sans the `:profiles` key)."
27-
#?(:cljs (:require-macros [active.clojure.record :refer (define-record-type)]))
28-
(:require [clojure.set :as set]
29-
[active.clojure.condition :as c]
30-
#?(:cljs [active.clojure.record])
31-
#?(:clj [active.clojure.record :refer :all]))
32-
#?(:clj (:import [java.net URL])))
27+
(:refer-clojure :exclude [boolean?])
28+
#?@
29+
(:clj
30+
[(:require
31+
[active.clojure.condition :as c]
32+
[active.clojure.record :refer :all]
33+
[clojure.set :as set])
34+
(:import java.net.URL)]
35+
:cljs
36+
[(:require [active.clojure.condition :as c]
37+
[clojure.set :as set]
38+
active.clojure.record)
39+
(:require-macros
40+
[active.clojure.record :refer [define-record-type]])]))
3341

3442
;; TODO
3543
;; - provide better support for reaching inside of collection ranges
3644

37-
(define-record-type
45+
(define-record-type
3846
^{:doc "Description of a range of values."}
3947
ValueRange ; used to be called Range, but conflicts with cljs.core/->Range
4048
(^{:doc "Make a [[Range]] range object.
@@ -185,7 +193,7 @@ Each profile has the same format as the top-level configuration itself
185193
(defn nonempty-string-range
186194
"Range for a non-empty string with optional max length."
187195
[& [max-length]]
188-
(make-scalar-range (str "non-empty string" (if (some? max-length)
196+
(make-scalar-range (str "non-empty string" (if (some? max-length)
189197
(str " with maximum length of " max-length)
190198
""))
191199
(fn [range path val]
@@ -351,7 +359,7 @@ Each profile has the same format as the top-level configuration itself
351359
(fn [this-range ky vl] ; we need the key & val functions
352360
(cond
353361
(nil? vl) {}
354-
362+
355363
(map? vl)
356364
(loop [kvs (seq vl)
357365
ret {}]
@@ -366,7 +374,7 @@ Each profile has the same format as the top-level configuration itself
366374
:else (recur (next kvs)
367375
(assoc ret k v))))
368376
ret))
369-
377+
370378
:else (make-range-error this-range ky vl))))
371379
(fn [this-range path f res val]
372380
(let [v ((range-completer this-range) this-range path val)]
@@ -388,7 +396,6 @@ Each profile has the same format as the top-level configuration itself
388396
(string? val) val
389397
;; FIXME: more cases?
390398
:else (make-range-error range path val))))))
391-
392399

393400
;; Schemas
394401

@@ -497,7 +504,7 @@ Each profile has the same format as the top-level configuration itself
497504
settings (map-schema-settings-map schema)
498505
sections (map-schema-sections-map schema)]
499506
(c/assert (not (range-error? cmap)) (pr-str cmap))
500-
(reduce (fn [res [k v]]
507+
(reduce (fn [res [k v]]
501508
(if-let [setting (get settings k)]
502509
((range-reduce (setting-range setting))
503510
(setting-range setting)
@@ -590,15 +597,15 @@ Each profile has the same format as the top-level configuration itself
590597
val1 (get c1 key)
591598
val2 (get c2 key)]
592599
(if (contains? settings-map key)
593-
(recur (assoc c
600+
(recur (assoc c
594601
;; that `nil` is a valid value
595-
key
602+
key
596603
(if (contains? c2 key)
597604
val2
598605
val1))
599606
(next all-keys))
600607
(if-let [section (get sections-map key)]
601-
(recur (assoc c key
608+
(recur (assoc c key
602609
(merge-config-objects-sans-profiles (section-schema section) (conj (vec path) key) (or val1 {}) (or val2 {})))
603610
(next all-keys))
604611
(c/error `merge-config-objects-sans-profiles
@@ -616,7 +623,7 @@ Each profile has the same format as the top-level configuration itself
616623
(c/error `merge-config-objects-sans-profiles
617624
(str "configuration at " path " is not a sequence: " (pr-str c2))
618625
path c2))
619-
626+
620627
(concat c1 c2))))
621628

622629
(defn merge-config-objects
@@ -639,7 +646,7 @@ Each profile has the same format as the top-level configuration itself
639646
(let [config-object (dissoc config-object :profiles)
640647
profiles (map (fn [n]
641648
(or (profile-map n)
642-
(c/error `apply-profiles "profile does not exist" n)))
649+
(c/error `apply-profiles "profile does not exist" n)))
643650
profile-names)]
644651
(reduce (partial merge-config-objects-sans-profiles schema []) config-object profiles))
645652
config-object))
@@ -666,7 +673,7 @@ Each profile has the same format as the top-level configuration itself
666673
(vals settings-map))))
667674

668675
(defn check-section
669-
[section val inherited-map path]
676+
[section val inherited-map path]
670677
(normalize&check-config-object-internal (section-schema section)
671678
val
672679
inherited-map
@@ -747,7 +754,7 @@ Each profile has the same format as the top-level configuration itself
747754
(recur (+ 1 idx)
748755
(rest els)
749756
(conj! res r))))))))))
750-
757+
751758
(defn normalize&check-config-object
752759
"Normalize and check the validity of a configuration object.
753760
@@ -833,7 +840,7 @@ Each profile has the same format as the top-level configuration itself
833840
[])]
834841
(concat triples-common triples-1 triples-2))))
835842

836-
843+
837844
(defn diff-configurations
838845
"Returns sequence of triples [path-vectors version-1 version-2] of settings that differ."
839846
[schema config-1 config-2]
@@ -861,7 +868,7 @@ Each profile has the same format as the top-level configuration itself
861868
(cond
862869
(map-schema? schema)
863870
(recurse (rest sections) cf)
864-
871+
865872
(sequence-schema? schema)
866873
(map (fn [subcf]
867874
(schemarec (sequence-schema-element-schema schema)
@@ -906,4 +913,3 @@ Each profile has the same format as the top-level configuration itself
906913
the remainder of the lines the field holds \".\"."
907914
[r]
908915
(any-range (one-of-range #{"."} nil) r))
909-

src/active/clojure/debug.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(ns active.clojure.debug)
22

3-
(defmacro pret [x]
3+
(defmacro pret [x]
44
"Print and return the argument."
5-
`(let [x# ~x]
6-
(println x#)
5+
`(let [x# ~x]
6+
(println x#)
77
x#))

src/active/clojure/lens.cljc

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,37 @@
11
(ns active.clojure.lens)
22

3-
(defprotocol Lens
4-
"Protocol for types that can be used as a lens, defined by a
5-
function to yank some value out of a given data value, and a function
6-
to shove an updated value back in."
7-
(-yank [lens data])
8-
(-shove [lens data v]))
9-
103
;; TODO document lens laws
114

125
(defn yank
136
"Yank a value from the given data value, as defined by the given
147
lens."
158
[data lens]
16-
(-yank lens data))
9+
(lens data))
1710

1811
(defn shove
1912
"Shove a new value v into the given data value, as defined by the
2013
given lens, and return the updated data structure."
2114
[data lens v]
22-
(-shove lens data v))
23-
24-
;; Keywords are lenses over a map (or object), focusing on the value associated with that keyword.
25-
(extend-type #?(:clj clojure.lang.Keyword) #?(:cljs cljs.core.Keyword)
26-
Lens
27-
(-yank [kw data] (kw data))
28-
(-shove [kw data v] (assoc data kw v)))
15+
(if (keyword? lens)
16+
(assoc data lens v)
17+
(lens data v)))
2918

3019
(defrecord ExplicitLens
3120
^{:private true}
3221
[yanker shover args]
33-
Lens
34-
(-yank [lens data] (apply yanker data args))
35-
(-shove [lens data v] (apply shover data v args))
3622
#?@(:clj [clojure.lang.IFn
37-
(invoke [this data] (-yank this data))
38-
(invoke [this data v] (-shove this data v))
23+
(invoke [this data] (apply yanker data args))
24+
(invoke [this data v] (apply shover data v args))
3925
(applyTo [this args]
4026
(let [args (object-array args)]
4127
(case (count args)
42-
1 (-yank this (aget args 0))
43-
2 (-shove this (aget args 0) (aget args 1))
28+
1 (yanker (aget args 0))
29+
2 (shover (aget args 0) (aget args 1))
4430
(throw #?(:clj (java.lang.IllegalArgumentException. (str "invalid number of arguments (" (count args) ") to lens")))
4531
#?(:cljs (str "invalid number of arguments (" (count args) ") to lens"))))))]
4632
:cljs [IFn
47-
(-invoke [this data] (-yank this data))
48-
(-invoke [this data v] (-shove this data v))]))
33+
(-invoke [this data] (apply yanker data args))
34+
(-invoke [this data v] (apply shover data v args))]))
4935

5036
(defn lens
5137
"Returns a new lens defined by the given yanker function, which
@@ -95,7 +81,6 @@
9581
value of the last one, in a data structure that the first one is put
9682
over."
9783
[l1 & lmore]
98-
(assert (not-any? #(not (satisfies? Lens %)) (cons l1 lmore)))
9984
(loop [res l1
10085
lmore lmore]
10186
(if (empty? lmore)
@@ -231,7 +216,7 @@
231216
mult-shove
232217
lenses))
233218

234-
;; not very general:
219+
;; not very general:
235220
;; (defn repeated
236221
;; [n]
237222
;; (lens #(take n (repeat %))

0 commit comments

Comments
 (0)