Skip to content

Commit 97be2c4

Browse files
authored
Merge pull request #247 from carloshernandez2/test-new-cats-mlet-macro
Test cats mlet macro that avoids nesting fn declarations
2 parents 73b4ecc + bf936d5 commit 97be2c4

File tree

5 files changed

+39
-16
lines changed

5 files changed

+39
-16
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog #
22

3+
## Version 2.4.3
4+
5+
Date: 2025-03-10
6+
7+
- Change mlet to declare monad functions on a single let form to avoid too long class file names
8+
39
## Version 2.4.2
410

511
Date: 2022-02-22

dev/user.clj

-5
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88
*namespaces*
99
['cats.core-spec
1010
'cats.builtin-spec
11-
'cats.applicative.validation-spec
1211
'cats.labs.channel-spec
13-
'cats.labs.state-spec
14-
'cats.labs.writer-spec
15-
'cats.labs.reader-spec
16-
'cats.labs.continuation-spec
1712
'cats.monad.identity-spec
1813
'cats.monad.either-spec
1914
'cats.monad.exception-spec

project.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(defproject funcool/cats "2.4.2"
1+
(defproject funcool/cats "2.4.3-beta.1"
22
:description "Category Theory abstractions for Clojure"
33
:url "https://github.com/funcool/cats"
44
:license {:name "BSD (2 Clause)"

src/cats/core.cljc

+30-8
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,22 @@
229229
;; Monadic Let Macro
230230
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
231231

232+
(defn- flatten-bindings
233+
[bindings]
234+
(filterv symbol? (tree-seq coll? seq bindings)))
235+
236+
(defn- parse-step
237+
[[l r] fn-bindings fn-sym]
238+
(case l
239+
:let
240+
(let [normalized-bindings (flatten-bindings (conj fn-bindings (take-nth 2 r)))]
241+
[`(let ~r (~fn-sym ~@normalized-bindings)) normalized-bindings])
242+
:when
243+
(let [normalized-bindings (flatten-bindings fn-bindings)]
244+
[`(bind (guard ~r) (partial ~fn-sym ~@normalized-bindings)) (conj normalized-bindings '_)])
245+
(let [normalized-bindings (flatten-bindings fn-bindings)]
246+
[`(bind ~r (partial ~fn-sym ~@normalized-bindings)) (conj normalized-bindings l)])))
247+
232248
#?(:clj
233249
(defmacro mlet
234250
"Monad composition macro that works like Clojure's
@@ -258,14 +274,20 @@
258274
(not-empty bindings)
259275
(even? (count bindings)))
260276
(throw (IllegalArgumentException. "bindings has to be a vector with even number of elements.")))
261-
(->> (reverse (partition 2 bindings))
262-
(reduce (fn [acc [l r]]
263-
(case l
264-
:let `(let ~r ~acc)
265-
:when `(bind (guard ~r)
266-
(fn [~(gensym)] ~acc))
267-
`(bind ~r (fn [~l] ~acc))))
268-
`(do ~@body)))))
277+
(let [first-sym (gensym)
278+
[let-body new-fn-bindings] (parse-step (take 2 bindings) [] first-sym)]
279+
(loop [rem-bindings (next (partition 2 bindings))
280+
current-sym first-sym
281+
fn-bindings new-fn-bindings
282+
new-bindings []]
283+
(if (empty? rem-bindings)
284+
(list 'let (into [] cat [[current-sym `(fn ~'_ ~(conj ['&] fn-bindings) ~@body)] new-bindings]) let-body)
285+
(let [new-sym (gensym)
286+
[expr new-fn-bindings] (parse-step (first rem-bindings) fn-bindings new-sym)]
287+
(recur (next rem-bindings)
288+
new-sym
289+
new-fn-bindings
290+
(into [] cat [[current-sym `(fn ~'_ ~(conj ['&] fn-bindings) ~expr)] new-bindings]))))))))
269291

270292
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
271293
;; Applicative Let Macro

test/cats/core_spec.cljc

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
(t/deftest mlet-tests
3232
(t/testing "Support regular let bindings inside mlet"
3333
(t/is (= (maybe/just 2)
34-
(m/mlet [i (maybe/just 1)
34+
(m/mlet [{i :i j :j} (maybe/just {:i 1 :j 0})
3535
:let [i (inc i)]]
36-
(m/return i)))))
36+
(m/return (+ i j))))))
3737

3838
(t/testing "Support :when guards inside its bindings"
3939
(t/is (= (maybe/nothing)

0 commit comments

Comments
 (0)