conjure-js 0.0.12 → 0.0.13
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.
- package/dist-cli/conjure-js.mjs +9360 -5298
- package/dist-vite-plugin/index.mjs +9463 -5185
- package/package.json +3 -1
- package/src/bin/cli.ts +2 -2
- package/src/bin/nrepl-symbol.ts +150 -0
- package/src/bin/nrepl.ts +289 -167
- package/src/bin/version.ts +1 -1
- package/src/clojure/core.clj +757 -29
- package/src/clojure/core.clj.d.ts +75 -131
- package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
- package/src/clojure/generated/clojure-core-source.ts +758 -29
- package/src/clojure/generated/clojure-set-source.ts +136 -0
- package/src/clojure/generated/clojure-walk-source.ts +72 -0
- package/src/clojure/set.clj +132 -0
- package/src/clojure/set.clj.d.ts +20 -0
- package/src/clojure/string.clj.d.ts +14 -0
- package/src/clojure/walk.clj +68 -0
- package/src/clojure/walk.clj.d.ts +7 -0
- package/src/core/assertions.ts +114 -6
- package/src/core/bootstrap.ts +337 -0
- package/src/core/conversions.ts +48 -31
- package/src/core/core-module.ts +303 -0
- package/src/core/env.ts +20 -6
- package/src/core/evaluator/apply.ts +40 -25
- package/src/core/evaluator/arity.ts +8 -8
- package/src/core/evaluator/async-evaluator.ts +565 -0
- package/src/core/evaluator/collections.ts +28 -5
- package/src/core/evaluator/destructure.ts +180 -69
- package/src/core/evaluator/dispatch.ts +12 -14
- package/src/core/evaluator/evaluate.ts +22 -20
- package/src/core/evaluator/expand.ts +45 -15
- package/src/core/evaluator/form-parsers.ts +178 -0
- package/src/core/evaluator/index.ts +7 -9
- package/src/core/evaluator/js-interop.ts +189 -0
- package/src/core/evaluator/quasiquote.ts +14 -8
- package/src/core/evaluator/recur-check.ts +6 -6
- package/src/core/evaluator/special-forms.ts +234 -191
- package/src/core/factories.ts +182 -3
- package/src/core/index.ts +54 -4
- package/src/core/module.ts +136 -0
- package/src/core/ns-forms.ts +107 -0
- package/src/core/printer.ts +371 -11
- package/src/core/reader.ts +84 -33
- package/src/core/registry.ts +209 -0
- package/src/core/runtime.ts +376 -0
- package/src/core/session.ts +253 -487
- package/src/core/stdlib/arithmetic.ts +528 -194
- package/src/core/stdlib/async-fns.ts +132 -0
- package/src/core/stdlib/atoms.ts +291 -56
- package/src/core/stdlib/errors.ts +54 -50
- package/src/core/stdlib/hof.ts +82 -166
- package/src/core/stdlib/js-namespace.ts +344 -0
- package/src/core/stdlib/lazy.ts +34 -0
- package/src/core/stdlib/maps-sets.ts +322 -0
- package/src/core/stdlib/meta.ts +61 -30
- package/src/core/stdlib/predicates.ts +325 -187
- package/src/core/stdlib/regex.ts +126 -98
- package/src/core/stdlib/seq.ts +564 -0
- package/src/core/stdlib/strings.ts +164 -135
- package/src/core/stdlib/transducers.ts +95 -100
- package/src/core/stdlib/utils.ts +292 -130
- package/src/core/stdlib/vars.ts +27 -27
- package/src/core/stdlib/vectors.ts +122 -0
- package/src/core/tokenizer.ts +2 -2
- package/src/core/transformations.ts +117 -9
- package/src/core/types.ts +98 -2
- package/src/host/node-host-module.ts +74 -0
- package/src/{vite-plugin-clj/nrepl-relay.ts → nrepl/relay.ts} +72 -11
- package/src/vite-plugin-clj/codegen.ts +87 -95
- package/src/vite-plugin-clj/index.ts +178 -23
- package/src/vite-plugin-clj/namespace-utils.ts +39 -0
- package/src/vite-plugin-clj/static-analysis.ts +211 -0
- package/src/clojure/demo.clj +0 -72
- package/src/clojure/demo.clj.d.ts +0 -0
- package/src/core/core-env.ts +0 -61
- package/src/core/stdlib/collections.ts +0 -739
- package/src/host/node.ts +0 -55
|
@@ -3,15 +3,26 @@
|
|
|
3
3
|
export const clojure_coreSource = `\
|
|
4
4
|
(ns clojure.core)
|
|
5
5
|
|
|
6
|
+
;; Host shims, for autocomplete only
|
|
7
|
+
(def all)
|
|
8
|
+
(def async)
|
|
9
|
+
(def catch*)
|
|
10
|
+
(def then)
|
|
11
|
+
|
|
6
12
|
(defmacro defn [name & fdecl]
|
|
7
13
|
(let [doc (if (string? (first fdecl)) (first fdecl) nil)
|
|
8
14
|
rest-decl (if doc (rest fdecl) fdecl)
|
|
9
15
|
arglists (if (vector? (first rest-decl))
|
|
10
16
|
(vector (first rest-decl))
|
|
11
|
-
(reduce (fn [acc arity] (conj acc (first arity))) [] rest-decl))
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
(reduce (fn [acc arity] (conj acc (first arity))) [] rest-decl))
|
|
18
|
+
meta-map (let [m (if doc {:doc doc :arglists arglists} {:arglists arglists})]
|
|
19
|
+
(if (:private (meta name)) (assoc m :private true) m))]
|
|
20
|
+
\`(def ~(with-meta name meta-map) (fn ~@rest-decl))))
|
|
21
|
+
|
|
22
|
+
(defmacro defn-
|
|
23
|
+
"Same as defn, but marks the var as private."
|
|
24
|
+
[name & fdecl]
|
|
25
|
+
(list* 'defn (with-meta name (assoc (meta name) :private true)) fdecl))
|
|
15
26
|
|
|
16
27
|
|
|
17
28
|
(defn vary-meta
|
|
@@ -36,10 +47,14 @@ export const clojure_coreSource = `\
|
|
|
36
47
|
(first (next coll)))
|
|
37
48
|
|
|
38
49
|
|
|
39
|
-
(defmacro when
|
|
50
|
+
(defmacro when
|
|
51
|
+
"Executes body when condition is true, otherwise returns nil."
|
|
52
|
+
[condition & body]
|
|
40
53
|
\`(if ~condition (do ~@body) nil))
|
|
41
54
|
|
|
42
|
-
(defmacro when-not
|
|
55
|
+
(defmacro when-not
|
|
56
|
+
"Executes body when condition is false, otherwise returns nil."
|
|
57
|
+
[condition & body]
|
|
43
58
|
\`(if ~condition nil (do ~@body)))
|
|
44
59
|
|
|
45
60
|
(defmacro if-let
|
|
@@ -100,9 +115,67 @@ export const clojure_coreSource = `\
|
|
|
100
115
|
\`(->> ~threaded ~@more))))
|
|
101
116
|
|
|
102
117
|
(defmacro comment
|
|
103
|
-
|
|
118
|
+
"Ignores body, yields nil"
|
|
104
119
|
[& body])
|
|
105
120
|
|
|
121
|
+
(defmacro as->
|
|
122
|
+
[expr name & forms]
|
|
123
|
+
\`(let [~name ~expr
|
|
124
|
+
~@(reduce (fn [acc form] (conj acc name form)) [] forms)]
|
|
125
|
+
~name))
|
|
126
|
+
|
|
127
|
+
(defmacro cond->
|
|
128
|
+
[expr & clauses]
|
|
129
|
+
(let [g (gensym "cv")
|
|
130
|
+
steps (reduce
|
|
131
|
+
(fn [acc pair]
|
|
132
|
+
(let [test (first pair)
|
|
133
|
+
form (second pair)
|
|
134
|
+
threaded (if (list? form)
|
|
135
|
+
\`(~(first form) ~g ~@(rest form))
|
|
136
|
+
\`(~form ~g))]
|
|
137
|
+
(conj acc \`(if ~test ~threaded ~g))))
|
|
138
|
+
[]
|
|
139
|
+
(partition-all 2 clauses))]
|
|
140
|
+
\`(let [~g ~expr
|
|
141
|
+
~@(reduce (fn [acc step] (conj acc g step)) [] steps)]
|
|
142
|
+
~g)))
|
|
143
|
+
|
|
144
|
+
(defmacro cond->>
|
|
145
|
+
[expr & clauses]
|
|
146
|
+
(let [g (gensym "cv")
|
|
147
|
+
steps (reduce
|
|
148
|
+
(fn [acc pair]
|
|
149
|
+
(let [test (first pair)
|
|
150
|
+
form (second pair)
|
|
151
|
+
threaded (if (list? form)
|
|
152
|
+
\`(~(first form) ~@(rest form) ~g)
|
|
153
|
+
\`(~form ~g))]
|
|
154
|
+
(conj acc \`(if ~test ~threaded ~g))))
|
|
155
|
+
[]
|
|
156
|
+
(partition-all 2 clauses))]
|
|
157
|
+
\`(let [~g ~expr
|
|
158
|
+
~@(reduce (fn [acc step] (conj acc g step)) [] steps)]
|
|
159
|
+
~g)))
|
|
160
|
+
|
|
161
|
+
(defmacro some->
|
|
162
|
+
[expr & forms]
|
|
163
|
+
(if (nil? forms)
|
|
164
|
+
expr
|
|
165
|
+
\`(let [v# ~expr]
|
|
166
|
+
(if (nil? v#)
|
|
167
|
+
nil
|
|
168
|
+
(some-> (-> v# ~(first forms)) ~@(rest forms))))))
|
|
169
|
+
|
|
170
|
+
(defmacro some->>
|
|
171
|
+
[expr & forms]
|
|
172
|
+
(if (nil? forms)
|
|
173
|
+
expr
|
|
174
|
+
\`(let [v# ~expr]
|
|
175
|
+
(if (nil? v#)
|
|
176
|
+
nil
|
|
177
|
+
(some->> (->> v# ~(first forms)) ~@(rest forms))))))
|
|
178
|
+
|
|
106
179
|
(defn constantly
|
|
107
180
|
"Returns a function that takes any number of arguments and returns x."
|
|
108
181
|
[x] (fn [& _] x))
|
|
@@ -400,7 +473,9 @@ export const clojure_coreSource = `\
|
|
|
400
473
|
([result] (rf result))
|
|
401
474
|
([result input] (rf result (f input))))))
|
|
402
475
|
([f coll]
|
|
403
|
-
(
|
|
476
|
+
(lazy-seq
|
|
477
|
+
(when-let [s (seq coll)]
|
|
478
|
+
(cons (f (first s)) (map f (rest s))))))
|
|
404
479
|
([f c1 c2]
|
|
405
480
|
(loop [s1 (seq c1)
|
|
406
481
|
s2 (seq c2)
|
|
@@ -433,7 +508,11 @@ export const clojure_coreSource = `\
|
|
|
433
508
|
(rf result input)
|
|
434
509
|
result)))))
|
|
435
510
|
([pred coll]
|
|
436
|
-
(
|
|
511
|
+
(lazy-seq
|
|
512
|
+
(when-let [s (seq coll)]
|
|
513
|
+
(if (pred (first s))
|
|
514
|
+
(cons (first s) (filter pred (rest s)))
|
|
515
|
+
(filter pred (rest s)))))))
|
|
437
516
|
|
|
438
517
|
(defn remove
|
|
439
518
|
"Returns a lazy sequence of the items in coll for which
|
|
@@ -467,7 +546,10 @@ export const clojure_coreSource = `\
|
|
|
467
546
|
(ensure-reduced result)
|
|
468
547
|
result)))))))
|
|
469
548
|
([n coll]
|
|
470
|
-
(
|
|
549
|
+
(lazy-seq
|
|
550
|
+
(when (pos? n)
|
|
551
|
+
(when-let [s (seq coll)]
|
|
552
|
+
(cons (first s) (take (dec n) (rest s))))))))
|
|
471
553
|
|
|
472
554
|
;; take-while: stateless transducer; emits reduced when pred fails
|
|
473
555
|
(defn take-while
|
|
@@ -484,7 +566,10 @@ export const clojure_coreSource = `\
|
|
|
484
566
|
(rf result input)
|
|
485
567
|
(reduced result))))))
|
|
486
568
|
([pred coll]
|
|
487
|
-
(
|
|
569
|
+
(lazy-seq
|
|
570
|
+
(when-let [s (seq coll)]
|
|
571
|
+
(when (pred (first s))
|
|
572
|
+
(cons (first s) (take-while pred (rest s))))))))
|
|
488
573
|
|
|
489
574
|
;; drop: stateful transducer; skips first n items
|
|
490
575
|
;; r >= 0 → still skipping; r < 0 → past the drop zone, start taking
|
|
@@ -504,7 +589,9 @@ export const clojure_coreSource = `\
|
|
|
504
589
|
result
|
|
505
590
|
(rf result input))))))))
|
|
506
591
|
([n coll]
|
|
507
|
-
(
|
|
592
|
+
(if (pos? n)
|
|
593
|
+
(lazy-seq (drop (dec n) (rest coll)))
|
|
594
|
+
(lazy-seq (seq coll)))))
|
|
508
595
|
|
|
509
596
|
(defn drop-last
|
|
510
597
|
"Return a sequence of all but the last n (default 1) items in coll"
|
|
@@ -538,7 +625,11 @@ export const clojure_coreSource = `\
|
|
|
538
625
|
(vreset! dropping false)
|
|
539
626
|
(rf result input))))))))
|
|
540
627
|
([pred coll]
|
|
541
|
-
(
|
|
628
|
+
(lazy-seq
|
|
629
|
+
(let [s (seq coll)]
|
|
630
|
+
(if (and s (pred (first s)))
|
|
631
|
+
(drop-while pred (rest s))
|
|
632
|
+
s)))))
|
|
542
633
|
|
|
543
634
|
;; map-indexed: stateful transducer; passes index and item to f
|
|
544
635
|
(defn map-indexed
|
|
@@ -556,7 +647,11 @@ export const clojure_coreSource = `\
|
|
|
556
647
|
([result input]
|
|
557
648
|
(rf result (f (vswap! i inc) input)))))))
|
|
558
649
|
([f coll]
|
|
559
|
-
(
|
|
650
|
+
(letfn [(step [i s]
|
|
651
|
+
(lazy-seq
|
|
652
|
+
(when-let [xs (seq s)]
|
|
653
|
+
(cons (f i (first xs)) (step (inc i) (rest xs))))))]
|
|
654
|
+
(step 0 coll))))
|
|
560
655
|
|
|
561
656
|
;; dedupe: stateful transducer; removes consecutive duplicates
|
|
562
657
|
(defn dedupe
|
|
@@ -608,23 +703,657 @@ export const clojure_coreSource = `\
|
|
|
608
703
|
;; ── Documentation ────────────────────────────────────────────────────────────
|
|
609
704
|
|
|
610
705
|
(defmacro doc [sym]
|
|
611
|
-
\`(let [v# ~sym
|
|
706
|
+
\`(let [v# (var ~sym)
|
|
612
707
|
m# (meta v#)
|
|
613
708
|
d# (:doc m#)
|
|
614
709
|
args# (:arglists m#)
|
|
615
710
|
args-str# (when args#
|
|
616
|
-
(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
(
|
|
711
|
+
(str "("
|
|
712
|
+
(reduce
|
|
713
|
+
(fn [acc# a#]
|
|
714
|
+
(if (= acc# "")
|
|
715
|
+
(str a#)
|
|
716
|
+
(str acc# " \\n " a#)))
|
|
717
|
+
""
|
|
718
|
+
args#)
|
|
719
|
+
")"))]
|
|
720
|
+
(println (str "-------------------------\\n"
|
|
721
|
+
~(str sym) "\\n"
|
|
722
|
+
(if args-str# (str args-str# "\\n") "")
|
|
723
|
+
" " (or d# "No documentation available.")))))
|
|
724
|
+
|
|
725
|
+
(defn make-err
|
|
627
726
|
"Creates an error map with type, message, data and optionally cause"
|
|
628
|
-
([type message] (err type message nil nil))
|
|
629
|
-
([type message data] (err type message data nil))
|
|
630
|
-
([type message data cause] {:type type :message message :data data :cause cause}))
|
|
727
|
+
([type message] (make-err type message nil nil))
|
|
728
|
+
([type message data] (make-err type message data nil))
|
|
729
|
+
([type message data cause] {:type type :message message :data data :cause cause}))
|
|
730
|
+
|
|
731
|
+
;; ── Sequence utilities ──────────────────────────────────────────────────────
|
|
732
|
+
|
|
733
|
+
(defn butlast
|
|
734
|
+
"Return a seq of all but the last item in coll, in linear time"
|
|
735
|
+
[coll]
|
|
736
|
+
(loop [ret [] s (seq coll)]
|
|
737
|
+
(if (next s)
|
|
738
|
+
(recur (conj ret (first s)) (next s))
|
|
739
|
+
(seq ret))))
|
|
740
|
+
|
|
741
|
+
(defn fnext
|
|
742
|
+
"Same as (first (next x))"
|
|
743
|
+
[x] (first (next x)))
|
|
744
|
+
|
|
745
|
+
(defn nfirst
|
|
746
|
+
"Same as (next (first x))"
|
|
747
|
+
[x] (next (first x)))
|
|
748
|
+
|
|
749
|
+
(defn nnext
|
|
750
|
+
"Same as (next (next x))"
|
|
751
|
+
[x] (next (next x)))
|
|
752
|
+
|
|
753
|
+
(defn nthrest
|
|
754
|
+
"Returns the nth rest of coll, coll when n is 0."
|
|
755
|
+
[coll n]
|
|
756
|
+
(loop [n n xs coll]
|
|
757
|
+
(if (and (pos? n) (seq xs))
|
|
758
|
+
(recur (dec n) (rest xs))
|
|
759
|
+
xs)))
|
|
760
|
+
|
|
761
|
+
(defn nthnext
|
|
762
|
+
"Returns the nth next of coll, (seq coll) when n is 0."
|
|
763
|
+
[coll n]
|
|
764
|
+
(loop [n n xs (seq coll)]
|
|
765
|
+
(if (and (pos? n) xs)
|
|
766
|
+
(recur (dec n) (next xs))
|
|
767
|
+
xs)))
|
|
768
|
+
|
|
769
|
+
(defn list*
|
|
770
|
+
"Creates a new seq containing the items prepended to the rest, the
|
|
771
|
+
last of which will be treated as a sequence."
|
|
772
|
+
([args] (seq args))
|
|
773
|
+
([a args] (cons a args))
|
|
774
|
+
([a b args] (cons a (cons b args)))
|
|
775
|
+
([a b c args] (cons a (cons b (cons c args))))
|
|
776
|
+
([a b c d & more]
|
|
777
|
+
(cons a (cons b (cons c (apply list* d more))))))
|
|
778
|
+
|
|
779
|
+
(defn mapv
|
|
780
|
+
"Returns a vector consisting of the result of applying f to the
|
|
781
|
+
set of first items of each coll, followed by applying f to the set
|
|
782
|
+
of second items in each coll, until any one of the colls is exhausted."
|
|
783
|
+
([f coll] (into [] (map f) coll))
|
|
784
|
+
([f c1 c2] (into [] (map f c1 c2)))
|
|
785
|
+
([f c1 c2 c3] (into [] (map f c1 c2 c3)))
|
|
786
|
+
([f c1 c2 c3 & colls] (into [] (apply map f c1 c2 c3 colls))))
|
|
787
|
+
|
|
788
|
+
(defn filterv
|
|
789
|
+
"Returns a vector of the items in coll for which
|
|
790
|
+
(pred item) returns logical true."
|
|
791
|
+
[pred coll]
|
|
792
|
+
(into [] (filter pred) coll))
|
|
793
|
+
|
|
794
|
+
(defn run!
|
|
795
|
+
"Runs the supplied procedure (via reduce), for purposes of side
|
|
796
|
+
effects, on successive items in the collection. Returns nil."
|
|
797
|
+
[proc coll]
|
|
798
|
+
(reduce (fn [_ x] (proc x) nil) nil coll))
|
|
799
|
+
|
|
800
|
+
(defn keep
|
|
801
|
+
"Returns a sequence of the non-nil results of (f item). Note,
|
|
802
|
+
this means false return values will be included. f must be free of
|
|
803
|
+
side-effects. Returns a transducer when no collection is provided."
|
|
804
|
+
([f]
|
|
805
|
+
(fn [rf]
|
|
806
|
+
(fn
|
|
807
|
+
([] (rf))
|
|
808
|
+
([result] (rf result))
|
|
809
|
+
([result input]
|
|
810
|
+
(let [v (f input)]
|
|
811
|
+
(if (nil? v)
|
|
812
|
+
result
|
|
813
|
+
(rf result v)))))))
|
|
814
|
+
([f coll]
|
|
815
|
+
(lazy-seq
|
|
816
|
+
(when-let [s (seq coll)]
|
|
817
|
+
(let [v (f (first s))]
|
|
818
|
+
(if (nil? v)
|
|
819
|
+
(keep f (rest s))
|
|
820
|
+
(cons v (keep f (rest s)))))))))
|
|
821
|
+
|
|
822
|
+
(defn keep-indexed
|
|
823
|
+
"Returns a sequence of the non-nil results of (f index item). Note,
|
|
824
|
+
this means false return values will be included. f must be free of
|
|
825
|
+
side-effects. Returns a stateful transducer when no collection is provided."
|
|
826
|
+
([f]
|
|
827
|
+
(fn [rf]
|
|
828
|
+
(let [i (volatile! -1)]
|
|
829
|
+
(fn
|
|
830
|
+
([] (rf))
|
|
831
|
+
([result] (rf result))
|
|
832
|
+
([result input]
|
|
833
|
+
(let [v (f (vswap! i inc) input)]
|
|
834
|
+
(if (nil? v)
|
|
835
|
+
result
|
|
836
|
+
(rf result v))))))))
|
|
837
|
+
([f coll]
|
|
838
|
+
(letfn [(step [i s]
|
|
839
|
+
(lazy-seq
|
|
840
|
+
(when-let [xs (seq s)]
|
|
841
|
+
(let [v (f i (first xs))]
|
|
842
|
+
(if (nil? v)
|
|
843
|
+
(step (inc i) (rest xs))
|
|
844
|
+
(cons v (step (inc i) (rest xs))))))))]
|
|
845
|
+
(step 0 coll))))
|
|
846
|
+
|
|
847
|
+
(defn mapcat
|
|
848
|
+
"Returns the result of applying concat to the result of applying map
|
|
849
|
+
to f and colls. Thus function f should return a collection. Returns
|
|
850
|
+
a transducer when no collections are provided."
|
|
851
|
+
([f]
|
|
852
|
+
(fn [rf]
|
|
853
|
+
(let [inner ((map f) (fn
|
|
854
|
+
([] (rf))
|
|
855
|
+
([result] (rf result))
|
|
856
|
+
([result input]
|
|
857
|
+
(reduce rf result input))))]
|
|
858
|
+
inner)))
|
|
859
|
+
([f coll]
|
|
860
|
+
(lazy-seq
|
|
861
|
+
(when-let [s (seq coll)]
|
|
862
|
+
(concat (f (first s)) (mapcat f (rest s))))))
|
|
863
|
+
([f coll & more]
|
|
864
|
+
(apply concat (apply map f coll more))))
|
|
865
|
+
|
|
866
|
+
(defn interleave
|
|
867
|
+
"Returns a lazy sequence of the first item in each coll, then the second etc.
|
|
868
|
+
Stops as soon as any coll is exhausted."
|
|
869
|
+
([c1 c2]
|
|
870
|
+
(lazy-seq
|
|
871
|
+
(let [s1 (seq c1) s2 (seq c2)]
|
|
872
|
+
(when (and s1 s2)
|
|
873
|
+
(cons (first s1) (cons (first s2) (interleave (rest s1) (rest s2))))))))
|
|
874
|
+
([c1 c2 & colls]
|
|
875
|
+
(lazy-seq
|
|
876
|
+
(let [seqs (map seq (cons c1 (cons c2 colls)))]
|
|
877
|
+
(when (every? some? seqs)
|
|
878
|
+
(concat (map first seqs) (apply interleave (map rest seqs))))))))
|
|
879
|
+
|
|
880
|
+
(defn interpose
|
|
881
|
+
"Returns a sequence of the elements of coll separated by sep.
|
|
882
|
+
Returns a transducer when no collection is provided."
|
|
883
|
+
([sep]
|
|
884
|
+
(fn [rf]
|
|
885
|
+
(let [started (volatile! false)]
|
|
886
|
+
(fn
|
|
887
|
+
([] (rf))
|
|
888
|
+
([result] (rf result))
|
|
889
|
+
([result input]
|
|
890
|
+
(if @started
|
|
891
|
+
(let [sepr (rf result sep)]
|
|
892
|
+
(if (reduced? sepr)
|
|
893
|
+
sepr
|
|
894
|
+
(rf sepr input)))
|
|
895
|
+
(do
|
|
896
|
+
(vreset! started true)
|
|
897
|
+
(rf result input))))))))
|
|
898
|
+
([sep coll]
|
|
899
|
+
(drop 1 (interleave (repeat sep) coll))))
|
|
900
|
+
|
|
901
|
+
;; ── Lazy concat (shadows native eager concat) ──────────────────────────────
|
|
902
|
+
(defn concat
|
|
903
|
+
"Returns a lazy seq representing the concatenation of the elements in the
|
|
904
|
+
supplied colls."
|
|
905
|
+
([] nil)
|
|
906
|
+
([x] (lazy-seq (seq x)))
|
|
907
|
+
([x y]
|
|
908
|
+
(lazy-seq
|
|
909
|
+
(let [s (seq x)]
|
|
910
|
+
(if s
|
|
911
|
+
(cons (first s) (concat (rest s) y))
|
|
912
|
+
(seq y)))))
|
|
913
|
+
([x y & zs]
|
|
914
|
+
(let [cat (fn cat [xy zs]
|
|
915
|
+
(lazy-seq
|
|
916
|
+
(let [xys (seq xy)]
|
|
917
|
+
(if xys
|
|
918
|
+
(cons (first xys) (cat (rest xys) zs))
|
|
919
|
+
(when (seq zs)
|
|
920
|
+
(cat (first zs) (next zs)))))))]
|
|
921
|
+
(cat (concat x y) zs))))
|
|
922
|
+
|
|
923
|
+
(defn iterate
|
|
924
|
+
"Returns a lazy sequence of x, (f x), (f (f x)) etc.
|
|
925
|
+
With 3 args, returns a finite sequence of n items (backwards compat)."
|
|
926
|
+
([f x]
|
|
927
|
+
(lazy-seq (cons x (iterate f (f x)))))
|
|
928
|
+
([f x n]
|
|
929
|
+
(loop [i 0 v x acc []]
|
|
930
|
+
(if (< i n)
|
|
931
|
+
(recur (inc i) (f v) (conj acc v))
|
|
932
|
+
acc))))
|
|
933
|
+
|
|
934
|
+
(defn repeatedly
|
|
935
|
+
"Takes a function of no args, presumably with side effects, and
|
|
936
|
+
returns a lazy infinite sequence of calls to it.
|
|
937
|
+
With 2 args (n f), returns a finite sequence of n calls."
|
|
938
|
+
([f] (lazy-seq (cons (f) (repeatedly f))))
|
|
939
|
+
([n f]
|
|
940
|
+
(loop [i 0 acc []]
|
|
941
|
+
(if (< i n)
|
|
942
|
+
(recur (inc i) (conj acc (f)))
|
|
943
|
+
acc))))
|
|
944
|
+
|
|
945
|
+
(defn cycle
|
|
946
|
+
"Returns a lazy infinite sequence of repetitions of the items in coll.
|
|
947
|
+
With 2 args (n coll), returns a finite sequence (backwards compat)."
|
|
948
|
+
([coll]
|
|
949
|
+
(lazy-seq
|
|
950
|
+
(when (seq coll)
|
|
951
|
+
(concat coll (cycle coll)))))
|
|
952
|
+
([n coll]
|
|
953
|
+
(let [s (into [] coll)]
|
|
954
|
+
(loop [i 0 acc []]
|
|
955
|
+
(if (< i n)
|
|
956
|
+
(recur (inc i) (into acc s))
|
|
957
|
+
acc)))))
|
|
958
|
+
|
|
959
|
+
(defn repeat
|
|
960
|
+
"Returns a lazy infinite sequence of xs.
|
|
961
|
+
With 2 args (n x), returns a finite sequence of n copies."
|
|
962
|
+
([x] (lazy-seq (cons x (repeat x))))
|
|
963
|
+
([n x] (repeat* n x)))
|
|
964
|
+
|
|
965
|
+
(defn range
|
|
966
|
+
"Returns a lazy infinite sequence of integers from 0.
|
|
967
|
+
With args, returns a finite sequence (delegates to native range*)."
|
|
968
|
+
([] (iterate inc 0))
|
|
969
|
+
([end] (range* end))
|
|
970
|
+
([start end] (range* start end))
|
|
971
|
+
([start end step] (range* start end step)))
|
|
972
|
+
|
|
973
|
+
(defn newline
|
|
974
|
+
"Writes a newline to *out*."
|
|
975
|
+
[] (println ""))
|
|
976
|
+
|
|
977
|
+
(defn dorun
|
|
978
|
+
"Forces realization of a (possibly lazy) sequence. Walks the sequence
|
|
979
|
+
without retaining the head. Returns nil."
|
|
980
|
+
[coll]
|
|
981
|
+
(when (seq coll)
|
|
982
|
+
(recur (rest coll))))
|
|
983
|
+
|
|
984
|
+
(defn doall
|
|
985
|
+
"Forces realization of a (possibly lazy) sequence. Unlike dorun,
|
|
986
|
+
retains the head and returns the seq."
|
|
987
|
+
[coll]
|
|
988
|
+
(dorun coll)
|
|
989
|
+
coll)
|
|
990
|
+
|
|
991
|
+
(defn take-nth
|
|
992
|
+
"Returns a sequence of every nth item in coll. Returns a stateful
|
|
993
|
+
transducer when no collection is provided."
|
|
994
|
+
([n]
|
|
995
|
+
(fn [rf]
|
|
996
|
+
(let [i (volatile! -1)]
|
|
997
|
+
(fn
|
|
998
|
+
([] (rf))
|
|
999
|
+
([result] (rf result))
|
|
1000
|
+
([result input]
|
|
1001
|
+
(let [idx (vswap! i inc)]
|
|
1002
|
+
(if (zero? (mod idx n))
|
|
1003
|
+
(rf result input)
|
|
1004
|
+
result)))))))
|
|
1005
|
+
([n coll]
|
|
1006
|
+
(sequence (take-nth n) coll)))
|
|
1007
|
+
|
|
1008
|
+
(defn partition
|
|
1009
|
+
"Returns a sequence of lists of n items each, at offsets step
|
|
1010
|
+
apart. If step is not supplied, defaults to n, i.e. the partitions
|
|
1011
|
+
do not overlap. If a pad collection is supplied, use its elements as
|
|
1012
|
+
necessary to complete last partition up to n items. In case there are
|
|
1013
|
+
not enough padding elements, return a partition with less than n items."
|
|
1014
|
+
([n coll] (partition n n coll))
|
|
1015
|
+
([n step coll]
|
|
1016
|
+
(loop [s (seq coll) acc []]
|
|
1017
|
+
(if (nil? s)
|
|
1018
|
+
acc
|
|
1019
|
+
(let [p (into [] (take n) s)]
|
|
1020
|
+
(if (< (count p) n)
|
|
1021
|
+
acc
|
|
1022
|
+
(recur (seq (drop step s)) (conj acc p)))))))
|
|
1023
|
+
([n step pad coll]
|
|
1024
|
+
(loop [s (seq coll) acc []]
|
|
1025
|
+
(if (nil? s)
|
|
1026
|
+
acc
|
|
1027
|
+
(let [p (into [] (take n) s)]
|
|
1028
|
+
(if (< (count p) n)
|
|
1029
|
+
(conj acc (into [] (take n) (concat p pad)))
|
|
1030
|
+
(recur (seq (drop step s)) (conj acc p))))))))
|
|
1031
|
+
|
|
1032
|
+
(defn partition-by
|
|
1033
|
+
"Applies f to each value in coll, splitting it each time f returns a
|
|
1034
|
+
new value. Returns a sequence of partitions. Returns a stateful
|
|
1035
|
+
transducer when no collection is provided."
|
|
1036
|
+
([f]
|
|
1037
|
+
(fn [rf]
|
|
1038
|
+
(let [pv (volatile! ::none)
|
|
1039
|
+
buf (volatile! [])]
|
|
1040
|
+
(fn
|
|
1041
|
+
([] (rf))
|
|
1042
|
+
([result]
|
|
1043
|
+
(let [b @buf]
|
|
1044
|
+
(vreset! buf [])
|
|
1045
|
+
(if (empty? b)
|
|
1046
|
+
(rf result)
|
|
1047
|
+
(rf (unreduced (rf result b))))))
|
|
1048
|
+
([result input]
|
|
1049
|
+
(let [v (f input)
|
|
1050
|
+
p @pv]
|
|
1051
|
+
(vreset! pv v)
|
|
1052
|
+
(if (or (= p ::none) (= v p))
|
|
1053
|
+
(do (vswap! buf conj input) result)
|
|
1054
|
+
(let [b @buf]
|
|
1055
|
+
(vreset! buf [input])
|
|
1056
|
+
(rf result b)))))))))
|
|
1057
|
+
([f coll]
|
|
1058
|
+
(lazy-seq
|
|
1059
|
+
(when-let [s (seq coll)]
|
|
1060
|
+
(let [fv (f (first s))
|
|
1061
|
+
run (into [] (cons (first s) (take-while #(= (f %) fv) (next s))))
|
|
1062
|
+
remaining (drop-while #(= (f %) fv) (next s))]
|
|
1063
|
+
(cons run (partition-by f remaining)))))))
|
|
1064
|
+
|
|
1065
|
+
(defn reductions
|
|
1066
|
+
"Returns a sequence of the intermediate values of the reduction (as
|
|
1067
|
+
by reduce) of coll by f, starting with init."
|
|
1068
|
+
([f coll]
|
|
1069
|
+
(if (empty? coll)
|
|
1070
|
+
(list (f))
|
|
1071
|
+
(reductions f (first coll) (rest coll))))
|
|
1072
|
+
([f init coll]
|
|
1073
|
+
(loop [acc [init] val init s (seq coll)]
|
|
1074
|
+
(if (nil? s)
|
|
1075
|
+
acc
|
|
1076
|
+
(let [nval (f val (first s))]
|
|
1077
|
+
(if (reduced? nval)
|
|
1078
|
+
(conj acc (unreduced nval))
|
|
1079
|
+
(recur (conj acc nval) nval (next s))))))))
|
|
1080
|
+
|
|
1081
|
+
(defn split-at
|
|
1082
|
+
"Returns a vector of [(take n coll) (drop n coll)]"
|
|
1083
|
+
[n coll]
|
|
1084
|
+
[(into [] (take n) coll) (into [] (drop n) coll)])
|
|
1085
|
+
|
|
1086
|
+
(defn split-with
|
|
1087
|
+
"Returns a vector of [(take-while pred coll) (drop-while pred coll)]"
|
|
1088
|
+
[pred coll]
|
|
1089
|
+
[(into [] (take-while pred) coll) (into [] (drop-while pred) coll)])
|
|
1090
|
+
|
|
1091
|
+
(defn merge-with
|
|
1092
|
+
"Returns a map that consists of the rest of the maps conj-ed onto
|
|
1093
|
+
the first. If a key occurs in more than one map, the mapping(s)
|
|
1094
|
+
from the latter (left-to-right) will be combined with the mapping in
|
|
1095
|
+
the result by calling (f val-in-result val-in-latter)."
|
|
1096
|
+
[f & maps]
|
|
1097
|
+
(reduce
|
|
1098
|
+
(fn [acc m]
|
|
1099
|
+
(if (nil? m)
|
|
1100
|
+
acc
|
|
1101
|
+
(reduce
|
|
1102
|
+
(fn [macc entry]
|
|
1103
|
+
(let [k (first entry)
|
|
1104
|
+
v (second entry)]
|
|
1105
|
+
(if (contains? macc k)
|
|
1106
|
+
(assoc macc k (f (get macc k) v))
|
|
1107
|
+
(assoc macc k v))))
|
|
1108
|
+
(or acc {})
|
|
1109
|
+
m)))
|
|
1110
|
+
nil
|
|
1111
|
+
maps))
|
|
1112
|
+
|
|
1113
|
+
(defn update-keys
|
|
1114
|
+
"m f => apply f to each key in m"
|
|
1115
|
+
[m f]
|
|
1116
|
+
(reduce
|
|
1117
|
+
(fn [acc entry]
|
|
1118
|
+
(assoc acc (f (first entry)) (second entry)))
|
|
1119
|
+
{}
|
|
1120
|
+
m))
|
|
1121
|
+
|
|
1122
|
+
(defn update-vals
|
|
1123
|
+
"m f => apply f to each val in m"
|
|
1124
|
+
[m f]
|
|
1125
|
+
(reduce
|
|
1126
|
+
(fn [acc entry]
|
|
1127
|
+
(assoc acc (first entry) (f (second entry))))
|
|
1128
|
+
{}
|
|
1129
|
+
m))
|
|
1130
|
+
|
|
1131
|
+
(defn not-empty
|
|
1132
|
+
"If coll is empty, returns nil, else coll"
|
|
1133
|
+
[coll]
|
|
1134
|
+
(when (seq coll) coll))
|
|
1135
|
+
|
|
1136
|
+
(defn memoize
|
|
1137
|
+
"Returns a memoized version of a referentially transparent function. The
|
|
1138
|
+
memoized version of the function keeps a cache of the mapping from arguments
|
|
1139
|
+
to results and, when calls with the same arguments are repeated often, has
|
|
1140
|
+
higher performance at the expense of higher memory use."
|
|
1141
|
+
[f]
|
|
1142
|
+
(let [mem (atom {})]
|
|
1143
|
+
(fn [& args]
|
|
1144
|
+
(let [cached (get @mem args ::not-found)]
|
|
1145
|
+
(if (= cached ::not-found)
|
|
1146
|
+
(let [ret (apply f args)]
|
|
1147
|
+
(swap! mem assoc args ret)
|
|
1148
|
+
ret)
|
|
1149
|
+
cached)))))
|
|
1150
|
+
|
|
1151
|
+
(defn trampoline
|
|
1152
|
+
"trampoline can be used to convert algorithms requiring mutual
|
|
1153
|
+
recursion without stack consumption. Calls f with supplied args, if
|
|
1154
|
+
any. If f returns a fn, calls that fn with no arguments, and
|
|
1155
|
+
continues to repeat, until the return value is not a fn, then
|
|
1156
|
+
returns that non-fn value."
|
|
1157
|
+
([f]
|
|
1158
|
+
(loop [ret (f)]
|
|
1159
|
+
(if (fn? ret)
|
|
1160
|
+
(recur (ret))
|
|
1161
|
+
ret)))
|
|
1162
|
+
([f & args]
|
|
1163
|
+
(loop [ret (apply f args)]
|
|
1164
|
+
(if (fn? ret)
|
|
1165
|
+
(recur (ret))
|
|
1166
|
+
ret))))
|
|
1167
|
+
|
|
1168
|
+
(defmacro with-redefs
|
|
1169
|
+
"binding => var-symbol temp-value-expr
|
|
1170
|
+
Temporarily redefines Vars while executing the body. The
|
|
1171
|
+
temp-value-exprs will be evaluated and each resulting value will
|
|
1172
|
+
replace in parallel the root value of its Var. Always restores
|
|
1173
|
+
the original values, even if body throws."
|
|
1174
|
+
[bindings & body]
|
|
1175
|
+
(let [pairs (partition 2 bindings)
|
|
1176
|
+
names (mapv first pairs)
|
|
1177
|
+
new-vals (mapv second pairs)
|
|
1178
|
+
orig-syms (mapv (fn [_] (gensym "orig")) names)]
|
|
1179
|
+
\`(let [~@(interleave orig-syms (map (fn [n] \`(var-get (var ~n))) names))]
|
|
1180
|
+
(try
|
|
1181
|
+
(do ~@(map (fn [n v] \`(alter-var-root (var ~n) (constantly ~v))) names new-vals)
|
|
1182
|
+
~@body)
|
|
1183
|
+
(finally
|
|
1184
|
+
~@(map (fn [n o] \`(alter-var-root (var ~n) (constantly ~o))) names orig-syms))))))
|
|
1185
|
+
|
|
1186
|
+
;; ── Macros: conditionals and control flow ───────────────────────────────────
|
|
1187
|
+
|
|
1188
|
+
(defmacro if-some
|
|
1189
|
+
"bindings => binding-form test
|
|
1190
|
+
If test is not nil, evaluates then with binding-form bound to the
|
|
1191
|
+
value of test, if not, yields else"
|
|
1192
|
+
([bindings then] \`(if-some ~bindings ~then nil))
|
|
1193
|
+
([bindings then else]
|
|
1194
|
+
(let [form (first bindings)
|
|
1195
|
+
tst (second bindings)]
|
|
1196
|
+
\`(let [temp# ~tst]
|
|
1197
|
+
(if (nil? temp#)
|
|
1198
|
+
~else
|
|
1199
|
+
(let [~form temp#]
|
|
1200
|
+
~then))))))
|
|
1201
|
+
|
|
1202
|
+
(defmacro when-some
|
|
1203
|
+
"bindings => binding-form test
|
|
1204
|
+
When test is not nil, evaluates body with binding-form bound to the
|
|
1205
|
+
value of test"
|
|
1206
|
+
[bindings & body]
|
|
1207
|
+
(let [form (first bindings)
|
|
1208
|
+
tst (second bindings)]
|
|
1209
|
+
\`(let [temp# ~tst]
|
|
1210
|
+
(when (some? temp#)
|
|
1211
|
+
(let [~form temp#]
|
|
1212
|
+
~@body)))))
|
|
1213
|
+
|
|
1214
|
+
(defmacro when-first
|
|
1215
|
+
"bindings => x xs
|
|
1216
|
+
Roughly the same as (when (seq xs) (let [x (first xs)] body)) but xs is evaluated only once"
|
|
1217
|
+
[bindings & body]
|
|
1218
|
+
(let [x (first bindings)
|
|
1219
|
+
xs (second bindings)]
|
|
1220
|
+
\`(let [temp# (seq ~xs)]
|
|
1221
|
+
(when temp#
|
|
1222
|
+
(let [~x (first temp#)]
|
|
1223
|
+
~@body)))))
|
|
1224
|
+
|
|
1225
|
+
(defn condp-emit [gpred gexpr clauses]
|
|
1226
|
+
(if (nil? clauses)
|
|
1227
|
+
\`(throw (ex-info (str "No matching clause: " ~gexpr) {}))
|
|
1228
|
+
(if (nil? (next clauses))
|
|
1229
|
+
(first clauses)
|
|
1230
|
+
\`(if (~gpred ~(first clauses) ~gexpr)
|
|
1231
|
+
~(second clauses)
|
|
1232
|
+
~(condp-emit gpred gexpr (next (next clauses)))))))
|
|
1233
|
+
|
|
1234
|
+
(defmacro condp
|
|
1235
|
+
"Takes a binary predicate, an expression, and a set of clauses.
|
|
1236
|
+
Each clause can take the form of either:
|
|
1237
|
+
test-expr result-expr
|
|
1238
|
+
The predicate is applied to each test-expr and the expression in turn."
|
|
1239
|
+
[pred expr & clauses]
|
|
1240
|
+
(let [gpred (gensym "pred__")
|
|
1241
|
+
gexpr (gensym "expr__")]
|
|
1242
|
+
\`(let [~gpred ~pred
|
|
1243
|
+
~gexpr ~expr]
|
|
1244
|
+
~(condp-emit gpred gexpr clauses))))
|
|
1245
|
+
|
|
1246
|
+
(defn case-emit [ge clauses]
|
|
1247
|
+
(if (nil? clauses)
|
|
1248
|
+
\`(throw (ex-info (str "No matching clause: " ~ge) {}))
|
|
1249
|
+
(if (nil? (next clauses))
|
|
1250
|
+
(first clauses)
|
|
1251
|
+
\`(if (= ~ge ~(first clauses))
|
|
1252
|
+
~(second clauses)
|
|
1253
|
+
~(case-emit ge (next (next clauses)))))))
|
|
1254
|
+
|
|
1255
|
+
(defmacro case
|
|
1256
|
+
"Takes an expression, and a set of clauses. Each clause can take the form of
|
|
1257
|
+
either:
|
|
1258
|
+
test-constant result-expr
|
|
1259
|
+
If no clause matches, and there is an odd number of forms (a default), the
|
|
1260
|
+
last expression is returned."
|
|
1261
|
+
[e & clauses]
|
|
1262
|
+
(let [ge (gensym "case__")]
|
|
1263
|
+
\`(let [~ge ~e]
|
|
1264
|
+
~(case-emit ge clauses))))
|
|
1265
|
+
|
|
1266
|
+
(defmacro dotimes
|
|
1267
|
+
"bindings => name n
|
|
1268
|
+
Repeatedly executes body (presumably for side-effects) with name
|
|
1269
|
+
bound to integers from 0 through n-1."
|
|
1270
|
+
[bindings & body]
|
|
1271
|
+
(let [i (first bindings)
|
|
1272
|
+
n (second bindings)]
|
|
1273
|
+
\`(let [n# ~n]
|
|
1274
|
+
(loop [~i 0]
|
|
1275
|
+
(when (< ~i n#)
|
|
1276
|
+
~@body
|
|
1277
|
+
(recur (inc ~i)))))))
|
|
1278
|
+
|
|
1279
|
+
(defmacro while
|
|
1280
|
+
"Repeatedly executes body while test expression is true. Presumes
|
|
1281
|
+
some side-effect will cause test to become false/nil."
|
|
1282
|
+
[test & body]
|
|
1283
|
+
\`(loop []
|
|
1284
|
+
(when ~test
|
|
1285
|
+
~@body
|
|
1286
|
+
(recur))))
|
|
1287
|
+
|
|
1288
|
+
(defmacro doseq
|
|
1289
|
+
"Repeatedly executes body (presumably for side-effects) with
|
|
1290
|
+
bindings. Supports :let, :when, and :while modifiers."
|
|
1291
|
+
[seq-exprs & body]
|
|
1292
|
+
(let [bindings (partition 2 seq-exprs)
|
|
1293
|
+
first-binding (first bindings)
|
|
1294
|
+
rest-bindings (next bindings)]
|
|
1295
|
+
(if (nil? first-binding)
|
|
1296
|
+
\`(do ~@body nil)
|
|
1297
|
+
(let [k (first first-binding)
|
|
1298
|
+
v (second first-binding)]
|
|
1299
|
+
(cond
|
|
1300
|
+
(= k :let)
|
|
1301
|
+
\`(let ~v (doseq ~(apply concat rest-bindings) ~@body))
|
|
1302
|
+
|
|
1303
|
+
(= k :when)
|
|
1304
|
+
\`(when ~v (doseq ~(apply concat rest-bindings) ~@body))
|
|
1305
|
+
|
|
1306
|
+
(= k :while)
|
|
1307
|
+
\`(if ~v (doseq ~(apply concat rest-bindings) ~@body) nil)
|
|
1308
|
+
|
|
1309
|
+
:else
|
|
1310
|
+
(if rest-bindings
|
|
1311
|
+
\`(run! (fn [~k] (doseq ~(apply concat rest-bindings) ~@body)) ~v)
|
|
1312
|
+
\`(run! (fn [~k] ~@body) ~v)))))))
|
|
1313
|
+
|
|
1314
|
+
(defmacro for
|
|
1315
|
+
"List comprehension. Takes a vector of one or more
|
|
1316
|
+
binding-form/collection-expr pairs, each followed by zero or more
|
|
1317
|
+
modifiers, and yields a sequence of evaluations of expr.
|
|
1318
|
+
Supported modifiers: :let, :when, :while."
|
|
1319
|
+
[seq-exprs & body]
|
|
1320
|
+
(let [bindings (partition 2 seq-exprs)
|
|
1321
|
+
first-binding (first bindings)
|
|
1322
|
+
rest-bindings (next bindings)]
|
|
1323
|
+
(if (nil? first-binding)
|
|
1324
|
+
\`(list ~@body)
|
|
1325
|
+
(let [k (first first-binding)
|
|
1326
|
+
v (second first-binding)]
|
|
1327
|
+
(cond
|
|
1328
|
+
(= k :let)
|
|
1329
|
+
\`(let ~v (for ~(apply concat rest-bindings) ~@body))
|
|
1330
|
+
|
|
1331
|
+
(= k :when)
|
|
1332
|
+
\`(if ~v (for ~(apply concat rest-bindings) ~@body) (list))
|
|
1333
|
+
|
|
1334
|
+
(= k :while)
|
|
1335
|
+
\`(if ~v (for ~(apply concat rest-bindings) ~@body) (list))
|
|
1336
|
+
|
|
1337
|
+
:else
|
|
1338
|
+
(if rest-bindings
|
|
1339
|
+
\`(mapcat (fn [~k] (for ~(apply concat rest-bindings) ~@body)) ~v)
|
|
1340
|
+
\`(map (fn [~k] ~@body) ~v)))))))
|
|
1341
|
+
|
|
1342
|
+
(defmacro with-out-str
|
|
1343
|
+
"Evaluates body in a context in which *out* is bound to a fresh string
|
|
1344
|
+
accumulator. Returns the string of all output produced by println, print,
|
|
1345
|
+
pr, prn, pprint and newline during the evaluation."
|
|
1346
|
+
[& body]
|
|
1347
|
+
\`(let [buf# (atom "")]
|
|
1348
|
+
(binding [*out* (fn [s#] (swap! buf# str s#))]
|
|
1349
|
+
~@body)
|
|
1350
|
+
@buf#))
|
|
1351
|
+
|
|
1352
|
+
(defmacro with-err-str
|
|
1353
|
+
"Like with-out-str but captures *err* output (warn, etc.)."
|
|
1354
|
+
[& body]
|
|
1355
|
+
\`(let [buf# (atom "")]
|
|
1356
|
+
(binding [*err* (fn [s#] (swap! buf# str s#))]
|
|
1357
|
+
~@body)
|
|
1358
|
+
@buf#))
|
|
1359
|
+
`
|