Repository navigation
Expand file tree
/
Copy pathutil.cljc
More file actions
170 lines (143 loc) · 4.71 KB
/
Copy pathutil.cljc
File metadata and controls
170 lines (143 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#_"SPDX-License-Identifier: GPL-3.0"
(ns emmy.util
"Shared utilities between clojure and clojurescript."
(:refer-clojure :exclude [bigint biginteger double long int uuid])
(:require #?(:clj [clojure.core :as core])
#?(:clj [clojure.math.numeric-tower :as nt])
#?(:cljs goog.math.Integer)
#?(:cljs goog.math.Long)
[clojure.walk :as w])
#?(:clj
(:import (clojure.lang BigInt)
(java.util UUID)
(java.util.concurrent TimeoutException)))
#?(:cljs
(:require-macros [emmy.util])))
(defn counted
"Takes a function and returns a pair of:
- an atom that keeps track of fn invocation counts,
- the instrumented fn"
([f] (counted f 0))
([f initial-count]
(let [count (atom initial-count)]
[count (fn [x]
(swap! count inc)
(f x))])))
(def compute-sqrt #?(:clj nt/sqrt :cljs Math/sqrt))
(def compute-expt #?(:clj nt/expt :cljs Math/pow))
(def compute-abs #?(:clj nt/abs :cljs Math/abs))
(def biginttype #?(:clj BigInt :cljs js/BigInt))
(def inttype #?(:clj Integer :cljs goog.math.Integer))
(def longtype #?(:clj Long :cljs goog.math.Long))
(defn keyset [m]
(into #{} (keys m)))
(defn map-vals
"Returns a map of identical type and key set to `m`, with each value `v`
transformed by the supplied function`f` into `(f v)`."
[f m]
(reduce-kv (fn [acc k v]
(assoc acc k (f v)))
(empty m)
m))
(defn re-matches?
"Returns true if s matches the regex pattern re, false otherwise."
[re s]
#?(:clj (.matches (re-matcher re s))
:cljs (.test re s)))
(defn bigint [x]
#?(:clj (core/bigint x)
:cljs (js/BigInt x)))
(defn bigint?
"Returns true if the supplied `x` is a `BigInt`, false otherwise."
[x]
#?(:clj (instance? BigInt x)
:cljs (= "bigint" (goog/typeOf x))))
(defn parse-bigint [x]
`(bigint ~x))
(defn biginteger [x]
#?(:clj (core/biginteger x)
:cljs (js/BigInt x)))
(defn int [x]
#?(:clj (core/int x)
:cljs (goog.math.Integer/fromNumber x)))
(defn long [x]
#?(:clj (core/long x)
:cljs (goog.math.Long/fromNumber x)))
(defn double [x]
#?(:clj (core/double x)
:cljs (if (number? x) x (js/Number x))))
(defn unsupported [s]
(throw
#?(:clj (UnsupportedOperationException. ^String s)
:cljs (js/Error s))))
(defn exception [s]
(throw
#?(:clj (Exception. ^String s)
:cljs (js/Error s))))
(defn uuid
"Returns a string containing a randomly generated unique identifier."
[]
(str
#?(:clj (UUID/randomUUID)
:cljs (random-uuid))))
(defn illegal [s]
(throw
#?(:clj (IllegalArgumentException. ^String s)
:cljs (js/Error s))))
(defn interrupted [s]
(throw
#?(:clj (InterruptedException. ^String s)
:cljs (js/Error s))))
(defn illegal-state [s]
(throw
#?(:clj (IllegalStateException. ^String s)
:cljs (js/Error s))))
(defn arithmetic-ex [s]
(throw
#?(:clj (ArithmeticException. s)
:cljs (js/Error s))))
(defn timeout-ex [s]
(throw
#?(:clj (TimeoutException. s)
:cljs (js/Error s))))
(defn failure-to-converge [s]
(throw
#?(:clj (Exception. ^String s)
:cljs (js/Error s))))
(defn throwable? [t]
(instance? #?(:clj Throwable :cljs js/Error) t))
(defn without-symbol-namespaces
"Walks x, removing namespaces from any symbols that are found.
Convenient in unit tests, where the distinction between symbols
in `clojure.core` vs. `cljs.core` is unimportant"
[x]
(w/postwalk (fn [s] (if (qualified-symbol? s) (symbol (name s)) s)) x))
(defmacro sci-macro
"Like `defmacro` but when emitting cljs, emits a function
with &env and &form prepended to arglists and :sci/macro metadata,
so that the macro can be imported into sci using copy-var."
[name & body]
(if (:ns &env)
(let [[doc body] (if (string? (first body))
[(first body) (rest body)]
[nil body])
[options body] (if (map? (first body))
[(first body) (rest body)]
[nil body])
arities (if (vector? (first body)) (list body) body)
arities (map (fn [[argv & body]]
(list (into '[&form &env] argv)
`(let [~'&env (assoc ~'&env :sci? true)]
~@body))) arities)]
`(defn ~(vary-meta name assoc :sci/macro true)
~@(when doc [doc])
~@(when options [options])
~@arities))
`(~'clojure.core/defmacro ~name ~@body)))
(defmacro copy-ns
([ns-sym sci-ns] `(copy-ns ~ns-sym ~sci-ns nil))
([ns-sym sci-ns opts]
(list 'sci.core/copy-ns
ns-sym
sci-ns
(merge {:copy-meta [:doc :arglists :macro :sci/macro :imported-from]} opts))))