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.
Files changed (77) hide show
  1. package/dist-cli/conjure-js.mjs +9360 -5298
  2. package/dist-vite-plugin/index.mjs +9463 -5185
  3. package/package.json +3 -1
  4. package/src/bin/cli.ts +2 -2
  5. package/src/bin/nrepl-symbol.ts +150 -0
  6. package/src/bin/nrepl.ts +289 -167
  7. package/src/bin/version.ts +1 -1
  8. package/src/clojure/core.clj +757 -29
  9. package/src/clojure/core.clj.d.ts +75 -131
  10. package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
  11. package/src/clojure/generated/clojure-core-source.ts +758 -29
  12. package/src/clojure/generated/clojure-set-source.ts +136 -0
  13. package/src/clojure/generated/clojure-walk-source.ts +72 -0
  14. package/src/clojure/set.clj +132 -0
  15. package/src/clojure/set.clj.d.ts +20 -0
  16. package/src/clojure/string.clj.d.ts +14 -0
  17. package/src/clojure/walk.clj +68 -0
  18. package/src/clojure/walk.clj.d.ts +7 -0
  19. package/src/core/assertions.ts +114 -6
  20. package/src/core/bootstrap.ts +337 -0
  21. package/src/core/conversions.ts +48 -31
  22. package/src/core/core-module.ts +303 -0
  23. package/src/core/env.ts +20 -6
  24. package/src/core/evaluator/apply.ts +40 -25
  25. package/src/core/evaluator/arity.ts +8 -8
  26. package/src/core/evaluator/async-evaluator.ts +565 -0
  27. package/src/core/evaluator/collections.ts +28 -5
  28. package/src/core/evaluator/destructure.ts +180 -69
  29. package/src/core/evaluator/dispatch.ts +12 -14
  30. package/src/core/evaluator/evaluate.ts +22 -20
  31. package/src/core/evaluator/expand.ts +45 -15
  32. package/src/core/evaluator/form-parsers.ts +178 -0
  33. package/src/core/evaluator/index.ts +7 -9
  34. package/src/core/evaluator/js-interop.ts +189 -0
  35. package/src/core/evaluator/quasiquote.ts +14 -8
  36. package/src/core/evaluator/recur-check.ts +6 -6
  37. package/src/core/evaluator/special-forms.ts +234 -191
  38. package/src/core/factories.ts +182 -3
  39. package/src/core/index.ts +54 -4
  40. package/src/core/module.ts +136 -0
  41. package/src/core/ns-forms.ts +107 -0
  42. package/src/core/printer.ts +371 -11
  43. package/src/core/reader.ts +84 -33
  44. package/src/core/registry.ts +209 -0
  45. package/src/core/runtime.ts +376 -0
  46. package/src/core/session.ts +253 -487
  47. package/src/core/stdlib/arithmetic.ts +528 -194
  48. package/src/core/stdlib/async-fns.ts +132 -0
  49. package/src/core/stdlib/atoms.ts +291 -56
  50. package/src/core/stdlib/errors.ts +54 -50
  51. package/src/core/stdlib/hof.ts +82 -166
  52. package/src/core/stdlib/js-namespace.ts +344 -0
  53. package/src/core/stdlib/lazy.ts +34 -0
  54. package/src/core/stdlib/maps-sets.ts +322 -0
  55. package/src/core/stdlib/meta.ts +61 -30
  56. package/src/core/stdlib/predicates.ts +325 -187
  57. package/src/core/stdlib/regex.ts +126 -98
  58. package/src/core/stdlib/seq.ts +564 -0
  59. package/src/core/stdlib/strings.ts +164 -135
  60. package/src/core/stdlib/transducers.ts +95 -100
  61. package/src/core/stdlib/utils.ts +292 -130
  62. package/src/core/stdlib/vars.ts +27 -27
  63. package/src/core/stdlib/vectors.ts +122 -0
  64. package/src/core/tokenizer.ts +2 -2
  65. package/src/core/transformations.ts +117 -9
  66. package/src/core/types.ts +98 -2
  67. package/src/host/node-host-module.ts +74 -0
  68. package/src/{vite-plugin-clj/nrepl-relay.ts → nrepl/relay.ts} +72 -11
  69. package/src/vite-plugin-clj/codegen.ts +87 -95
  70. package/src/vite-plugin-clj/index.ts +178 -23
  71. package/src/vite-plugin-clj/namespace-utils.ts +39 -0
  72. package/src/vite-plugin-clj/static-analysis.ts +211 -0
  73. package/src/clojure/demo.clj +0 -72
  74. package/src/clojure/demo.clj.d.ts +0 -0
  75. package/src/core/core-env.ts +0 -61
  76. package/src/core/stdlib/collections.ts +0 -739
  77. 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
- (if doc
13
- \`(def ~name (with-meta (fn ~@rest-decl) {:doc ~doc :arglists '~arglists}))
14
- \`(def ~name (with-meta (fn ~@rest-decl) {:arglists '~arglists})))))
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 [condition & body]
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 [condition & body]
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
- ; Ignores body, yields nil
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
- (sequence (map f) coll))
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
- (sequence (filter pred) coll)))
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
- (sequence (take n) coll)))
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
- (sequence (take-while pred) coll)))
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
- (sequence (drop n) coll)))
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
- (sequence (drop-while pred) coll)))
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
- (sequence (map-indexed f) coll)))
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
- (reduce
617
- (fn [acc# a#]
618
- (if (= acc# "")
619
- (str "(" a# ")")
620
- (str acc# "\\n" "(" a# ")")))
621
- ""
622
- args#))]
623
- (println (str (if args-str# (str args-str# "\\n\\n") "")
624
- (or d# "No documentation available.")))))
625
-
626
- (defn err
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
+ `