beginners

James Amberger 2025-06-04T23:27:49.800099Z

Musing on applying transducer to conj, below the fold.

💡 1
🤔 1
James Amberger 2025-06-04T23:28:51.101999Z

;; suppose:
(def a (atom nil))

(defn callback'
  [x]
  (swap! a conj x))

;; need to transform x before conj
;; want to use transducer.
;; why? Maybe transducer exists already,
;; maybe transformation is best expressed as transducer (stateful, filters, etc)
;;
;; well, conj is a reducing function, so we can replace it
;; with (xf conj) thus:

(def xf
  (comp
   (filter odd?)
   (map inc)))

(def rf
  (xf conj))

(defn callback [x]
  (swap! a rf x))

;; simulate activity:
(callback 7) ; (8)
(callback 8) ; (8)
(callback 7) ; (8 8)

;; of course, callback could have been
(defn callback' [x]
  (if (odd? x)
    (swap! a conj (inc x))
    @a))

;; and if you had a stateful transducer you could have written callback as a let-over-lambda:
(def xf'' (dedupe))
(def rf'' (xf'' conj))

;; equivalent callback'':
(let [b (atom nil)]
  (defn callback'' [x]
    (let [b' @b]
      (reset! b x)
      (if (not= b' x)
        (swap! a conj x)
        @a))))

;; but i think it more likely to screw this up than just
;; (comp (dedupe) (filter odd?) (map inc) #_(maybe more transducers et cetera))
;; which makes this another way to say how crazy good the transducer concept is

ghadi 2025-06-05T00:07:11.124699Z

swap! may call its argument more than once, so stateful transducers are precluded

James Amberger 2025-06-05T00:14:59.740079Z

thanks—nice catch