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