Skip to content

Instantly share code, notes, and snippets.

@kawas44
Created July 31, 2023 19:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kawas44/c569be3284e9d2a9f2281230eb5171d9 to your computer and use it in GitHub Desktop.
Save kawas44/c569be3284e9d2a9f2281230eb5171d9 to your computer and use it in GitHub Desktop.
Play with Clojure IReduceInit interface
(ns reducible
(:require [clojure.java.io :as io])
(:import (clojure.lang IReduceInit)))
(defn file-lines
"Returns a reducible collection over lines of a file.
It is not lazy and releases resources when reduction ends."
[filepath]
(reify IReduceInit
(reduce [_this rf start]
(with-open [rdr (io/reader filepath)]
(loop [acc start]
(if (reduced? acc)
(unreduced acc)
(if-some [line (.readLine rdr)]
(recur (rf acc line))
acc)))))))
(comment
(def lines (file-lines "tmp/lines.txt")) ;; returns a reified object
;;;; works with reduce ... sometimes :/
(reduce conj [] lines) ;; returns lines
(reduce conj lines) ;; will fail on missing start value!
;; the contract of core/reduce is odd!
;;;; works with reducers/reduce
(require '[clojure.core.reducers :as r])
(r/reduce conj lines) ;; returns lines
;; the contract of reducers/reduce is better!
;;;; works with anything that use `reduce` under the hood
(mapv identity lines) ;; mapv, filterv
(group-by first lines)
(set lines)
(into #{} lines)
(into [] (take 2) lines) ;; transducers
(run! prn lines)
;;;; works with reducers
(require '[clojure.string :as str])
(def lines-upper (r/map str/upper-case lines)) ;; returns a reified object
(r/fold conj lines-upper) ;; returns lines to uppercase
;;
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment