Hey!
I'm using nubank/state-flow which heavily relies on funcool/cats monads, and compiling code that gets written to disk is for most purposes not possible because the resulting class names of heavily nested anonymous functions would surpass the OS limit. A different approach for implementing the mlet macro would create small enough class names. Details of my proposal in the thread 🧵
(m/mlet [a (maybe/just 1)
b (m/return (inc a))
c (m/return (inc b))]
(m/return (* c 2)))
Currently the result of the macro expansion of the call above looks like this:
(cats.core/bind
(maybe/just 1)
(clojure.core/fn
[a]
(cats.core/bind
(m/return (inc a))
(clojure.core/fn [b] (cats.core/bind (m/return (inc b)) (clojure.core/fn [c] (do (m/return (* c 2)))))))))
The more bindings we add the more nested functions are created. having bindings from a to s gives the following resulting names when writing the compiled classes to disk:
my_dear_test$monad_test_nested_mlet
my_dear_test$monad_test_nested_mlet$fn__174484
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497$fn__174498
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497$fn__174498$fn__174499
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497$fn__174498$fn__174499$fn__174500
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497$fn__174498$fn__174499$fn__174500$fn__174501
my_dear_test$monad_test_nested_mlet$fn__174484$fn__174485$fn__174486$fn__174487$fn__174488$fn__174489$fn__174490$fn__174491$fn__174492$fn__174493$fn__174494$fn__174495$fn__174496$fn__174497$fn__174498$fn__174499$fn__174500$fn__174501$fn__174502
By having the result of the macro expansion be something like this:
(let*
[G__174687
(clojure.core/fn [& [a b c]] (m/return (* c 2)))
G__174686
(clojure.core/fn [& [a b]] (cats.core/bind (m/return (inc b)) (clojure.core/partial G__174687 a b)))
G__174685
(clojure.core/fn [& [a]] (cats.core/bind (m/return (inc a)) (clojure.core/partial G__174686 a)))]
(cats.core/bind (maybe/just 1) (clojure.core/partial G__174685)))
The resulting class names for the mlet with bindings from a to s are the following:
my_dear_test$monad_test_listed_mlet
my_dear_test$monad_test_listed_mlet$G__174523__174665
my_dear_test$monad_test_listed_mlet$G__174524__174659
my_dear_test$monad_test_listed_mlet$G__174525__174653
my_dear_test$monad_test_listed_mlet$G__174526__174647
my_dear_test$monad_test_listed_mlet$G__174527__174641
my_dear_test$monad_test_listed_mlet$G__174528__174635
my_dear_test$monad_test_listed_mlet$G__174529__174629
my_dear_test$monad_test_listed_mlet$G__174530__174623
my_dear_test$monad_test_listed_mlet$G__174531__174617
my_dear_test$monad_test_listed_mlet$G__174532__174611
my_dear_test$monad_test_listed_mlet$G__174533__174605
my_dear_test$monad_test_listed_mlet$G__174534__174599
my_dear_test$monad_test_listed_mlet$G__174535__174593
my_dear_test$monad_test_listed_mlet$G__174536__174587
my_dear_test$monad_test_listed_mlet$G__174537__174581
my_dear_test$monad_test_listed_mlet$G__174538__174575
my_dear_test$monad_test_listed_mlet$G__174539__174569
my_dear_test$monad_test_listed_mlet$G__174540__174563
my_dear_test$monad_test_listed_mlet$G__174541__174557
my_dear_test$monad_test_listed_mlet$G__174542__174551
my_dear_test$monad_test_listed_mlet$G__174543__174545
WDYT?
As a reference, here's the mlet with bindings from a to s:
(defn monad-test-nested-mlet
[]
(m/mlet [a (maybe/just 1)
b (maybe/just (inc a))
c (maybe/just (inc b))
d (maybe/just (inc c))
e (maybe/just (inc d))
f (maybe/just (inc e))
g (maybe/just (inc f))
h (maybe/just (inc g))
i (maybe/just (inc h))
j (maybe/just (inc i))
k (maybe/just (inc j))
l (maybe/just (inc k))
m (maybe/just (inc l))
n (maybe/just (inc m))
o (maybe/just (inc n))
p (maybe/just (inc o))
q (maybe/just (inc p))
r (maybe/just (inc q))
s (maybe/just (inc r))]
(m/return (* s 2))))