Skip to content

Instantly share code, notes, and snippets.

View favila's full-sized avatar

Francis Avila favila

View GitHub Profile
@favila
favila / restore_datoms.clj
Last active September 30, 2021 03:50
Restore a datomic database "manually", i.e. from raw datoms. Useful for memory databases. Context: https://groups.google.com/d/msg/datomic/BkTdKYB3WpE/AKfqKYqPONMJ
(ns favila.datomic-util.restore-datoms
"A \"manual\" datomic database restore.
Writes raw datoms (stored in a stream written by d/datoms) to an empty database.
Useful for memory databases: you can write out all the datoms in it, then read
them into another database. (Note mem dbs have no log or retractions)."
(:require [datomic.api :as d]
[clojure.edn :as edn]))
(defrecord datom [e a v tx added?])
@favila
favila / jforms.html
Created March 6, 2015 04:23
Old experiment with the XForms master dependency directed graph algorithm http://www.w3.org/TR/xforms11/#rpm-processing-recalc-mddg
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>xforms dependency algorithm</title>
</head>
<body>
<div>
<form action="" method="post" accept-charset="utf-8">
<ol style="list-style-type:lower-latin">
@favila
favila / bootstrap-txes-0-9-5173.edn
Created June 1, 2015 20:51
Find the bootstrap transactions for a datomic database. Bootstrap transactions are the first few transactions which create all the datoms necessary for datomic to work (e.g., the initial partitions, types, attributes, and tx functions). They are not accessible directly via the transaction log.
;; Result of bootstrap-txes function above under datomic 0.9.5173
;; Bootstrap transactions are 0,
;; More bootstrap transactions or datoms may be added in later datomic versions.
;; First non-bootstrap transaction is always T >= 1000.
;; Format is [[t [[e a v tx added] ...] ...] ...]
[[0
[[0 10 :db.part/db 13194139533312 true]
[1 10 :db/add 13194139533312 true]
[2 10 :db/retract 13194139533312 true]
@favila
favila / tempid-idx.clj
Created June 1, 2015 23:26
AtomicInteger counter with overflow handled correctly
(import '[java.util.concurrent.atomic AtomicInteger])
(set! *unchecked-math* :warn-on-boxed)
(def ^AtomicInteger counter (AtomicInteger.))
(defn next-tempid-idx [^AtomicInteger i]
(unchecked-subtract -1000000 (bit-and (.getAndIncrement i) 0x7fffffff)))
@favila
favila / cond-assoc-from.clj
Created July 13, 2015 17:14
Conditionally assoc values of a source map to a target map.
(defmacro cond-assoc-from
"Using a source ILookup (map, vector, etc) and a target IAssoc (map), for each
clause bind the value of source at given source-key to a binding expression
and assoc the target-expression (evaluated with bindings) to the target under target-key.
If the source-key's value is nil, skip the clause. Example:
(cond-assoc-from {:a [1 2]} {}
[a-1 a-2] :a :A (inc a-2)
b :b :B (inc b))
;=> {:A 3}"
@favila
favila / wrap-highlighted.cljc
Created August 22, 2015 00:31
Wrap-highlighted, for splitting strings with elasticsearch highlighting.
(defn wrap-highlighted
"Return a vector of string parts where highlighted runs are replaced with (f highlighted-string)."
[f s]
(->> (re-seq #"<em>(.+?)</em>|.+?(?=<em>|$)" s)
(map (fn [[all highlighted]]
(if (nil? highlighted)
all
(f highlighted))))))
@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
@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 / 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 / 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}}