Skip to content

Instantly share code, notes, and snippets.

View favila's full-sized avatar

Francis Avila favila

View GitHub Profile
@favila
favila / sha1-hash-stream.clj
Created July 13, 2016 21:04
sha1 hash a stream in clojure
(defn sha1-hash-stream [^InputStream stream]
(let [buffer (byte-array 8192)
md (MessageDigest/getInstance "SHA-1")]
(loop []
(let [taken (.read stream buffer 0 8192)]
(if (> taken 0)
(do (.update md buffer 0 taken)
(recur))
(.digest md))))))
@favila
favila / datomic-reset-attributes.clj
Last active January 12, 2025 14:04
Datomic transaction functions to "reset" attributes: i.e. make them have a post-transaction value you specify without having to enumerate the retractions.
(def tx-fns
[{:db/ident :db.fn/reset-attribute-values
:db/doc "Transaction function which accepts an entity identifier, attribute identifier
and set of values and expands to any additions and retractions necessary to
make the final post-transaction value of the attribute match the provided
values. Attribute values must be scalars.
If multiple values are provided on a cardinality-one attribute you will get a
datom conflict exception at transaction time."
:db/fn (d/function
@favila
favila / datomic-edn-handlers.clj
Created April 5, 2016 00:24
Utilities for making it easier to read edn files. Also includes tag readers that datomic uses.
(ns favila.read-edn.tag-readers
"Common tag-reader maps for edn."
(:require datomic.db
datomic.function
datomic.codec)
(:import java.net.URI))
(defmethod print-method URI [^URI x ^Writer w]
(doto w
(.write "#uri ")
@favila
favila / advent_a6.clj
Last active April 3, 2016 06:31
Solutions to advent of code, day 6 in clojure. Written in response to this post: https://groups.google.com/d/msg/clojure/iQRKhOKxh5g/5P5_QticBAAJ
(ns advent.a6
(:require [clojure.java.io :as io])
(:import (clojure.lang PersistentVector)))
(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)
(defn input []
(slurp (io/resource "day6-part1-input")))
@favila
favila / stm-example-core.clj
Created April 2, 2016 09:22
Somewhat realistic example of using refs and dosync, compared with an equivalent approach using an atom.
(ns stm-example.core
"A somewhat realistic use of Clojure refs and dosync.
In most cases you should use an atom: it will be simpler and faster.
But you may need to use refs when:
* You need to return something other than the entire state from a swap!. E.g.,
the id of a newly-created user, or whether an action succeeded. You can
emulate this by adding a \"return value\" key to the atom on any state
@favila
favila / unsigned-to-signed-literal.clj
Created March 10, 2016 23:14
Basic code pattern to get signed hex literal (for java) from an unsigned hex literal
(defn signed-literal [^String unsigned-hex-str]
(let [s (-> (Long/parseUnsignedLong unsigned-hex-str 16)
(Long/toString 16))]
(if (.startsWith s "-")
(str "-0x" (subs s 1))
(str "0x" s))))
@favila
favila / entity-changes.clj
Last active October 16, 2019 13:14
enity-changes Return transaction history for a datomic entity and its components.
(require '[datomic.api :as d])
(defn entity-changes
"Return transaction history for an entity and its components.
Returns a sequence of maps, each is the transaction map (tx metadata) plus a
key `:entity-changes`, which is a nested map of keys: entity id, attribute
ident, `:db/add` or `:db/retract`, and the value added or retracted, e.g.:
{12345678910 {:long-card-1-attr {:db/retract 1
:db/add 0}
:long-card-many-attr {:db/add #{0}}
@favila
favila / grouper-by.cljc
Last active February 5, 2016 16:13
grouper-by function: a reduction function compatible with `transduce` which performs an independent stepwise reduction on each group: `group-by` without the intermediate group collections!
(defn grouper-by
"Return a reducing function which reduces items in groups (determined by
result of `(keyfn item)`) independently using optional transducer
`group-xform` and reduction function `group-rf` (which should have 3 arities).
The supplied reducing and transducing functions may be stateful: their state
will be isolated to a particular group.
The returned reducing function should be run with `transduce`
or `finalizing-reduce` (not `reduce`, which does not use the \"finalize\"
@favila
favila / unique.clj
Created November 11, 2015 21:12
Efficient clojure(script) unique? function, optionally taking a key function.
(defn unique?
"Return true if a collection's items are unique, else false
With a key function, will return true if `(map keyfn coll)` is unique, else false."
([coll] (unique? coll identity))
([coll keyfn]
(or (set? coll) (map? coll)
(some? (reduce
(fn [seen x]
(let [k (keyfn x)]
@favila
favila / buffered_reduce.cljc
Created September 1, 2015 15:19
Transduction with a user-controllable state buffer which is flushed on transduction finalization. Useful for writing transducers which sometimes process items differently based on a look-ahead condition.
(defn buffered-reduce
"Return a transducer wrapping `reduction-fn` which holds on to an internal
buffer volatile (initialized with nil) which will be flushed (via `reduce`)
when the transducer is closed.
The `reduction-fn` should accept a combining function, an accumulating value,
a current value, and a buffer volatile. This function should return a new
accumulating value via 0, 1 or many calls to `(xf r new-value)`. It may also
manipulate the contents of the volatile for its own use. If anything is found
in the buffer when the reduction is complete, its items will be added to the