Skip to content

Commit b2a8a86

Browse files
authored
Merge pull request #71 from madstap/add-more-pure-clojure-things
Add more pure core fns
2 parents fcc8251 + 350f287 commit b2a8a86

File tree

1 file changed

+233
-0
lines changed

1 file changed

+233
-0
lines changed

src/jank/clojure/core.jank

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,71 @@
15311531
(cat (first zs) (next zs)))))))]
15321532
(cat (concat x y) zs))))
15331533

1534+
(defn juxt
1535+
"Takes a set of functions and returns a fn that is the juxtaposition
1536+
of those fns. The returned fn takes a variable number of args, and
1537+
returns a vector containing the result of applying each fn to the
1538+
args (left-to-right).
1539+
((juxt a b c) x) => [(a x) (b x) (c x)]"
1540+
([f]
1541+
(fn
1542+
([] [(f)])
1543+
([x] [(f x)])
1544+
([x y] [(f x y)])
1545+
([x y z] [(f x y z)])
1546+
([x y z & args] [(apply f x y z args)])))
1547+
([f g]
1548+
(fn
1549+
([] [(f) (g)])
1550+
([x] [(f x) (g x)])
1551+
([x y] [(f x y) (g x y)])
1552+
([x y z] [(f x y z) (g x y z)])
1553+
([x y z & args] [(apply f x y z args) (apply g x y z args)])))
1554+
([f g h]
1555+
(fn
1556+
([] [(f) (g) (h)])
1557+
([x] [(f x) (g x) (h x)])
1558+
([x y] [(f x y) (g x y) (h x y)])
1559+
([x y z] [(f x y z) (g x y z) (h x y z)])
1560+
([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)])))
1561+
([f g h & fs]
1562+
(let [fs (list* f g h fs)]
1563+
(fn
1564+
([] (reduce #(conj %1 (%2)) [] fs))
1565+
([x] (reduce #(conj %1 (%2 x)) [] fs))
1566+
([x y] (reduce #(conj %1 (%2 x y)) [] fs))
1567+
([x y z] (reduce #(conj %1 (%2 x y z)) [] fs))
1568+
([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs))))))
1569+
1570+
(defn partial
1571+
"Takes a function f and fewer than the normal arguments to f, and
1572+
returns a fn that takes a variable number of additional args. When
1573+
called, the returned function calls f with args + additional args."
1574+
([f] f)
1575+
([f arg1]
1576+
(fn
1577+
([] (f arg1))
1578+
([x] (f arg1 x))
1579+
([x y] (f arg1 x y))
1580+
([x y z] (f arg1 x y z))
1581+
([x y z & args] (apply f arg1 x y z args))))
1582+
([f arg1 arg2]
1583+
(fn
1584+
([] (f arg1 arg2))
1585+
([x] (f arg1 arg2 x))
1586+
([x y] (f arg1 arg2 x y))
1587+
([x y z] (f arg1 arg2 x y z))
1588+
([x y z & args] (apply f arg1 arg2 x y z args))))
1589+
([f arg1 arg2 arg3]
1590+
(fn
1591+
([] (f arg1 arg2 arg3))
1592+
([x] (f arg1 arg2 arg3 x))
1593+
([x y] (f arg1 arg2 arg3 x y))
1594+
([x y z] (f arg1 arg2 arg3 x y z))
1595+
([x y z & args] (apply f arg1 arg2 arg3 x y z args))))
1596+
([f arg1 arg2 arg3 & more]
1597+
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
1598+
15341599
; Returns the first logical true value of (pred x) for any x in coll,
15351600
; else nil. One common idiom is to use a set as pred, for example
15361601
; this will return :fred if :fred is in the sequence, otherwise nil:
@@ -2112,6 +2177,50 @@
21122177
(cons (map first ss) (step (map rest ss)))))))]
21132178
(map #(apply f %) (step (conj colls c3 c2 c1))))))
21142179

2180+
(defmacro doto
2181+
"Evaluates x then calls all of the methods and functions with the
2182+
value of x supplied at the front of the given arguments. The forms
2183+
are evaluated in order. Returns x."
2184+
[x & forms]
2185+
(let [gx (gensym)]
2186+
`(let [~gx ~x]
2187+
~@(map (fn [f]
2188+
(with-meta
2189+
(if (seq? f)
2190+
`(~(first f) ~gx ~@(next f))
2191+
`(~f ~gx))
2192+
(meta f)))
2193+
forms)
2194+
~gx)))
2195+
2196+
(defn map-indexed
2197+
"Returns a lazy sequence consisting of the result of applying f to 0
2198+
and the first item of coll, followed by applying f to 1 and the second
2199+
item in coll, etc, until coll is exhausted. Thus function f should
2200+
accept 2 arguments, index and item. Returns a stateful transducer when
2201+
no collection is provided."
2202+
([f]
2203+
(fn [rf]
2204+
(let [i (volatile! -1)]
2205+
(fn
2206+
([] (rf))
2207+
([result] (rf result))
2208+
([result input]
2209+
(rf result (f (vswap! i inc) input)))))))
2210+
([f coll]
2211+
(let [mapi (fn mapi [idx coll]
2212+
(lazy-seq
2213+
(when-let [s (seq coll)]
2214+
(if (chunked-seq? s)
2215+
(let [c (chunk-first s)
2216+
size (int (count c))
2217+
b (chunk-buffer size)]
2218+
(dotimes [i size]
2219+
(chunk-append b (f (+ idx i) (nth c i))))
2220+
(chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s))))
2221+
(cons (f idx (first s)) (mapi (inc idx) (rest s)))))))]
2222+
(mapi 0 coll))))
2223+
21152224
(defn keep
21162225
"Returns a lazy sequence of the non-nil results of (f item). Note,
21172226
this means false return values will be included. f must be free of
@@ -2143,6 +2252,42 @@
21432252
(keep f (rest s))
21442253
(cons x (keep f (rest s))))))))))
21452254

2255+
(defn keep-indexed
2256+
"Returns a lazy sequence of the non-nil results of (f index item). Note,
2257+
this means false return values will be included. f must be free of
2258+
side-effects. Returns a stateful transducer when no collection is
2259+
provided."
2260+
([f]
2261+
(fn [rf]
2262+
(let [iv (volatile! -1)]
2263+
(fn
2264+
([] (rf))
2265+
([result] (rf result))
2266+
([result input]
2267+
(let [i (vswap! iv inc)
2268+
v (f i input)]
2269+
(if (nil? v)
2270+
result
2271+
(rf result v))))))))
2272+
([f coll]
2273+
(let [keepi (fn keepi [idx coll]
2274+
(lazy-seq
2275+
(when-let [s (seq coll)]
2276+
(if (chunked-seq? s)
2277+
(let [c (chunk-first s)
2278+
size (count c)
2279+
b (chunk-buffer size)]
2280+
(dotimes [i size]
2281+
(let [x (f (+ idx i) (nth c i))]
2282+
(when-not (nil? x)
2283+
(chunk-append b x))))
2284+
(chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s))))
2285+
(let [x (f idx (first s))]
2286+
(if (nil? x)
2287+
(keepi (inc idx) (rest s))
2288+
(cons x (keepi (inc idx) (rest s)))))))))]
2289+
(keepi 0 coll))))
2290+
21462291
(defn take
21472292
([n]
21482293
(fn [rf]
@@ -2420,6 +2565,31 @@
24202565
run (cons fst (take-while #(= fv (f %)) (next s)))]
24212566
(cons run (partition-by f (lazy-seq (drop (count run) s)))))))))
24222567

2568+
(defn frequencies
2569+
"Returns a map from distinct items in coll to the number of times
2570+
they appear."
2571+
[coll]
2572+
;; OPTIMIZE: transient
2573+
(reduce (fn [counts x]
2574+
(assoc counts x (inc (get counts x 0))))
2575+
{} coll))
2576+
2577+
(defn reductions
2578+
"Returns a lazy seq of the intermediate values of the reduction (as
2579+
per reduce) of coll by f, starting with init."
2580+
([f coll]
2581+
(lazy-seq
2582+
(if-let [s (seq coll)]
2583+
(reductions f (first s) (rest s))
2584+
(list (f)))))
2585+
([f init coll]
2586+
(if (reduced? init)
2587+
(list (deref init))
2588+
(cons init
2589+
(lazy-seq
2590+
(when-let [s (seq coll)]
2591+
(reductions f (f init (first s)) (rest s))))))))
2592+
24232593
(defn into
24242594
"Returns a new coll consisting of to-coll with all of the items of
24252595
from-coll conjoined. A transducer may be supplied."
@@ -2819,6 +2989,45 @@
28192989
(mapcat walk (children node))))))]
28202990
(walk root)))
28212991

2992+
(defn distinct
2993+
"Returns a lazy sequence of the elements of coll with duplicates removed.
2994+
Returns a stateful transducer when no collection is provided."
2995+
([]
2996+
(fn [rf]
2997+
(let [seen (volatile! #{})]
2998+
(fn
2999+
([] (rf))
3000+
([result] (rf result))
3001+
([result input]
3002+
(if (contains? (deref seen) input)
3003+
result
3004+
(do (vswap! seen conj input)
3005+
(rf result input))))))))
3006+
([coll]
3007+
(let [step (fn step [xs seen]
3008+
(lazy-seq
3009+
((fn [[f :as xs] seen]
3010+
(when-let [s (seq xs)]
3011+
(if (contains? seen f)
3012+
(recur (rest s) seen)
3013+
(cons f (step (rest s) (conj seen f))))))
3014+
xs seen)))]
3015+
(step coll #{}))))
3016+
3017+
(defn distinct?
3018+
"Returns true if no two of the arguments are ="
3019+
([x] true)
3020+
([x y] (not (= x y)))
3021+
([x y & more]
3022+
(if (not= x y)
3023+
(loop [s #{x y} [x & etc :as xs] more]
3024+
(if xs
3025+
(if (contains? s x)
3026+
false
3027+
(recur (conj s x) etc))
3028+
true))
3029+
false)))
3030+
28223031
; Returns a lazy sequence of the items in coll for which
28233032
; (pred item) returns logical true. pred must be free of side-effects.
28243033
; Returns a transducer when no collection is provided.
@@ -2866,6 +3075,30 @@
28663075
([pred coll]
28673076
(filter (complement pred) coll)))
28683077

3078+
(defn dedupe
3079+
"Returns a lazy sequence removing consecutive duplicates in coll.
3080+
Returns a transducer when no collection is provided."
3081+
([]
3082+
(fn [rf]
3083+
(let [pv (volatile! ::none)]
3084+
(fn
3085+
([] (rf))
3086+
([result] (rf result))
3087+
([result input]
3088+
(let [prior (deref pv)]
3089+
(vreset! pv input)
3090+
(if (= prior input)
3091+
result
3092+
(rf result input))))))))
3093+
([coll]
3094+
(let [step (fn step [prior xs]
3095+
(lazy-seq
3096+
(when-some [[x & more] (seq xs)]
3097+
(if (= x prior)
3098+
(step prior more)
3099+
(cons x (step x more))))))]
3100+
(step ::none coll))))
3101+
28693102
; Takes an expression and a set of test/form pairs. Threads expr (via ->)
28703103
; through each form for which the corresponding test
28713104
; expression is true. Note that, unlike cond branching, cond-> threading does

0 commit comments

Comments
 (0)