Skip to content

Instantly share code, notes, and snippets.

(defmacro defnormalizer
[name m]
{:pre (map? m)}
(let [arg 'rec
body
(reduce-kv
(fn [m k v]
((if (sequential? v) assoc-in assoc)
m
v
@bsless
bsless / maybe-apply.clj
Created September 3, 2020 07:32
Incremental cond-> in clojure
(defmacro maybe-apply->
[x & pfs]
(assert (even? (count pfs)))
(let [g (gensym)
bs (mapcat (fn [[p f]] `(~g (if (-> ~g ~p) (-> ~g ~f) ~g))) (partition 2 pfs))]
`(let [~g ~x
~@bs]
~g)))
;;; example:
@bsless
bsless / lit-bin.clj
Created September 2, 2020 13:52
Literal binary strings in Clojure
(import '[javax.xml.bind DatatypeConverter])
(defn hex->bin [x] (DatatypeConverter/parseHexBinary x))
(defn bin->hex [x] (DatatypeConverter/printHexBinary x))
(def bin (type (hex->bin "a1")))
(defmethod print-method bin
[v ^java.io.Writer w]
(.write w "#x \"")
(.write w (bin->hex v))
@bsless
bsless / build.sh
Last active September 3, 2020 08:15
Dockerized lein uberjar
# This is just a contrived example
sudo docker run -e "TOKEN=$TOKEN" --rm -v "$PWD":/usr/src/app -w /usr/src/app clojure:openjdk-14-lein-2.9.3 lein do clean, test, uberjar
@bsless
bsless / etl.clj
Created August 14, 2020 11:43
Generalized ETL flow with core.async
(defn etl
"Perform ETL flow with parallelism `n`.
Will return a channel which will block until the job is done.
Receives the following arguments:
- `prepare-fn`: returns an input collection from `in`.
- `xf`: transducer, will perform the E, T stages.
- `rf`: Reducing function, will combine results in some manner.
- `init`: initial value to reduce xf results into.
- `post-fn`: perform final operation on value returned after reduction
- `in`: input argument to process.
@bsless
bsless / trie.clj
Last active August 13, 2020 05:58
build a trie from strings
(defn chat
[^CharSequence cs index]
(.charAt cs ^int index))
(defn strlen
[^CharSequence s]
(.length s))
(defn trie
@bsless
bsless / concatenation.clj
Created August 4, 2020 06:40
sort of cons-ing of sequences
(require '[clojure.core.protocols :as p])
(deftype Concatenation [coll1 coll2]
clojure.lang.IReduceInit
(reduce [_ f init]
(reduce f coll2 (reduce f init coll1 )))
clojure.lang.Seqable
(seq [this] (concat coll1 coll2)))
(defn concatenation
@bsless
bsless / minimal-state-monad.clj
Last active August 30, 2020 07:04
The bare minimum to create a state monad in Clojure. No good reason, really.
(definline pair
[x y]
`(clojure.lang.MapEntry/create ~x ~y))
(defn create-state-monad
[init]
(fn [f in]
(let [state' (f init in)]
(pair (create-state-monad state') state'))))
@bsless
bsless / fast-query-string.clj
Created July 31, 2020 13:15
Build up a simple query string really fast
(import '[java.net URLEncoder])
(definline url-encode
[s]
`(URLEncoder/encode (str ~s) "utf8"))
(defn sb-qs-kvrf
[^StringBuilder sb k v]
(let [k (url-encode (name k))
v (url-encode v)]
@bsless
bsless / foldmaps.clj
Last active October 21, 2020 06:57
Annotated version for Oded
(defn fold-by ;;; similar to group-by
([kf ;;; Key function to group on
op ;;; operation how to combine two elements under the same key
coll] ;; collection of maps
(persistent!
(reduce
(fn [ret x] ;; ret is a map from (kf x) to xs, similar to the result of group-by
(let [k (kf x) ;; derive the key
v (get ret k)] ;; get the value already associated with the key if it exists
(assoc! ret