I've been using tacit programming intensively to the extent I get rid of most variables. I use both syntactic threading macros and functional combinators to achieve this. It is a double-edged sword in that it can make code as ugly as the original code it is trying to improve upon, but working without variables isn't that difficult nor does it lead me to intense clusterfucks. Composing lambdas contribute to this a lot more though.
As for making things clearer for everyone, well, this is code I work on solo (hobby), but I think providing example inputs as well as debugging macros can help a lot. Consider the following:
(defn parse-it [dependencies]
(pp->> dependencies
str
str/split-lines
(keep (|| re-matches #"- (\d+(?:\.\d+)?) -> \[((?:\d+(?:\.\d+)?(?:, ?)?)+)\]"))
(>>- (map-> (juxt-> second
(->> third (re-seq #"(?:\d+(?:\.\d+)?)")))))))
(parse-it (str "- 4 -> [1, 2, 3]\n"
"- 5 -> [4, 2]\n"
"- 6 -> [1, 2, 5]"))
;; The use of pp->> will lead to this getting printed
;; ->> dependencies : "- 4 -> [1, 2, 3]
;; - 5 -> [4, 2]
;; - 6 -> [1, 2, 5]"
;; str/split-lines : ["- 4 -> [1, 2, 3]"
;; "- 5 -> [4, 2]"
;; "- 6 -> [1, 2, 5]"]
;; (keep (|| re-matches #"- (\d+(?:\.\d+)... : (["- 4 -> [1, 2, 3]" "4" "1, 2, 3"]
;; ["- 5 -> [4, 2]" "5" "4, 2"]
;; ["- 6 -> [1, 2, 5]" "6" "1, 2, 5"])
;; (>>- (map-> (juxt-> second (->> third ... : (("4" ("1" "2" "3"))
;; ("5" ("4" "2"))
;; ("6" ("1" "2" "5")))
In the end I think it doesn't really bring a lot, but it's especially useful in making short piece of code more readable:
(->> [1 2 3 4]
(map (when| odd? inc)))
;; vs
(->> [1 2 3 4]
(map (fn [x]
(if (odd? x)
(inc x)
x))))
;; result (2 2 4 4)
Or this:
(-> k-or-ks (when-not-> coll? list)
(map-> ...do-something))
;;vs
(let [ks (if (coll? k-or-ks)
k-or-ks
(list k-or-ks))]
(map ...do-something
ks))
Or even this:
(-> 1 (juxtm-> :incd inc :decd dec))
;; vs
(let [n 1]
{:incd (inc n)
:decd (dec n)})
Granted I have insane shits like this teleport arrow (very useful though):
(-> '(1 2)
(•- (conj (-• first dec)))) ;; => (0 1 2)
Or this >-args "fletching"
(-> {:a 1 :b 2}
(•- (-> (>-args (-> (/ (-> :a) (-> :b))))
(->> (assoc (-•) :result))))) ;; => {:a 1, :b 2, :result 1/2}
I actually write this kind of stuff in my code ahahaha (the right move is to implement assoc-> of course hahahaha). Now there are combinators I wrote I never use, like departializers, unappliers, argument shifters, etc