Skip to content

Instantly share code, notes, and snippets.

@bhb
bhb / README.md
Last active May 12, 2020
Clojure friendly mode, inspired by https://github.com/slipset/friendly
View README.md
@bhb
bhb / multimethod_selector.clj
Last active Nov 13, 2019 — forked from mtnygard/multimethod_selector.clj
A clojure.spec.gen.alpha generator that picks a multimethod implementation from the known set.
View multimethod_selector.clj
(require '[clojure.spec.gen.alpha :as sgen])
;; original
(defn multimethod-selector
"Returns a generator that picks one dispatch value from the known
dispatch values of a multimethod. Defers the lookup of dispatch
values until sampling time, so any defmethods evaluated after the
generator is created may still be selected."
[s]
#(sgen/bind
View loan-payment-data.json
[{"loan":{"id":1,"borrower_id":1,"amount":10984659,"term":120},"period":{"start_at":"2017-05-22T00:00:00-06:00","end_at":"2017-06-21T23:59:59-06:00"},"principal":57702,"interest":83752,"rate_annual":900,"service_fee":{"amount":0,"rate":0}},{"loan":{"id":1,"borrower_id":1,"amount":10984659,"term":120},"period":{"start_at":"2017-06-22T00:00:00-06:00","end_at":"2017-07-21T23:59:59-06:00"},"principal":56262,"interest":80629,"rate_annual":900,"service_fee":{"amount":0,"rate":0}},{"loan":{"id":1,"borrower_id":1,"amount":10984659,"term":120},"period":{"start_at":"2017-07-22T00:00:00-06:00","end_at":"2017-08-21T23:59:59-06:00"},"principal":58577,"interest":82877,"rate_annual":900,"service_fee":{"amount":0,"rate":0}},{"loan":{"id":1,"borrower_id":1,"amount":10984659,"term":120},"period":{"start_at":"2017-08-22T00:00:00-06:00","end_at":"2017-09-21T23:59:59-06:00"},"principal":59026,"interest":82428,"rate_annual":900,"service_fee":{"amount":0,"rate":0}},{"loan":{"id":1,"borrower_id":1,"amount":10984659,"term":120},"peri
@bhb
bhb / tempids.clj
Created May 13, 2019
Dependent effects with tempids
View tempids.clj
[{:op :create-company
:name "Foobar Company"
:id "tempid/company"}
{:op :create-employee
:name "Alice"
:company_id "tempid/company"
:id "tempid/user1"}
{:op :create-employee
:name "Bob"
:company_id "tempid/company"
View gist:d2fd7413a5d68f404b871526c58b4bc3
Run this to launch REPL
rlwrap clj -Srepro -Sdeps '{:deps {speculative {:mvn/version "0.0.3"} expound {:mvn/version "0.7.2"} org.clojure/test.check {:mvn/version "0.9.0"} org.clojure/clojurescript {:mvn/version "1.10.520"}}}' -e "(require '[expound.alpha :as expound] '[cljs.core.specs.alpha]) (set! clojure.spec.alpha/*explain-out* (expound/custom-printer {:print-specs? false :show-valid-values? true :theme :figwheel-theme}))" -m cljs.main -re node
Then run this in REPL
(require '[expound.alpha :as expound] '[cljs.core.specs.alpha] '[speculative.instrument :as i]) (i/instrument) (set! cljs.spec.alpha/*explain-out* (expound/custom-printer {:print-specs? false :show-valid-values? true :theme :figwheel-theme}))
@bhb
bhb / test_helper.clj
Last active Mar 6, 2019
Test helpers when using clojure.spec
View test_helper.clj
(ns foo.test-helper
(:require [clojure.spec :as s]
[clojure.spec.test :as st]
[clojure.string :as str]
[clojure.test :refer :all]
[clojure.test.check.generators :as gen]
[clojure.test.check.random :refer [IRandom]]
[clojure.test.check.rose-tree :as rose]))
(defn instrument-all
@bhb
bhb / cljs_1_10_339.cljs
Created Feb 9, 2019
Custom explain-out with different versions of CLJS
View cljs_1_10_339.cljs
;; Note this uses clojure 1.9, not 1.10 like other examples
;; clj -Srepro -Sdeps '{:deps {org.clojure/test.check {:mvn/version "0.9.0"} org.clojure/clojure {:mvn/version "1.9.0"} org.clojure/clojurescript {:mvn/version "1.10.339"}}}' --main cljs.main --repl
in cljs.main --repl
(require '[cljs.spec.alpha :as s])
(require '[cljs.spec.test.alpha :as st])
(require '[clojure.core.specs.alpha])
;; instrumenting a function
(s/fdef foobar :args (s/cat :x int?))
@bhb
bhb / ex.clj
Last active Nov 25, 2018
Replacing default spec printer for experimentation
View ex.clj
;; launch with
;; clj -Srepro -Sdeps '{:deps {org.clojure/test.check {:mvn/version "0.9.0"} org.clojure/clojure {:mvn/version "1.10.0-beta8"}}}'
(require '[clojure.spec.alpha :as s])
(require '[clojure.spec.test.alpha :as st])
;; instrumenting a function
(s/fdef foobar :args (s/cat :x int?))
(defn foobar [x] x)
@bhb
bhb / init.cljs
Last active Nov 7, 2018 — forked from borkdude/init.cljs
Speculative + Expound in Klipse
View init.cljs
(require '[cljs.spec.alpha :as s])
(require '[cljs.spec.test.alpha :as stest])
(require '[expound.alpha :as expound])
(require '[speculative.core])
(set! s/*explain-out* (expound/custom-printer {:show-valid-values? true}))
(stest/instrument `map)
(try
(map 'lol 'lol)
(catch :default e
(println (.-message e))))
@bhb
bhb / blockchain-w-spec.md
Last active Oct 25, 2018
Building a blockchain, assisted by Clojure spec
View blockchain-w-spec.md

Building a blockchain, assisted by Clojure spec

In an effort to gain at least a superficial understanding of the technical implementation of cryptocurrencies, I recently worked my way through "Learn Blockchains by Building One" using Clojure.

This was a good chance to experiment with using spec in new ways. At work, we primarily use spec to validate our global re-frame state and to validate data at system boundaries. For this project, I experimented with using instrumentation much more pervasively than I had done elsewhere.

This is not a guide to spec (there are already many excellent resources for this). Rather, it's an experience report exploring what went well, what is still missing, and quite a few unanswered questions for future research. If you have solutions for any of the problems I've presented, please let me know!

You don't need to know or care about blockchains to understand the code be