Skip to content

Instantly share code, notes, and snippets.

@bhb
bhb / repl.txt
Created September 25, 2018 01:45
Confusing behavior from `keys*`
➜ ~ rlwrap clj -Srepro -Sdeps '{:deps {org.clojure/spec.alpha {:mvn/version "0.2.176"}}}'
Clojure 1.9.0
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::point1 (s/cat :x int? :y int?))
user/point1
user=> (s/def ::x int?)
:user/x
user=> (s/def ::y int?)
:user/y
@bhb
bhb / simple_coerce.clj
Last active September 21, 2018 19:00
A naive implementation of opt-in coercion.
;; Code is largely copied from
;; https://github.com/wilkerlucio/spec-coerce/blob/master/src/spec_coerce/core.cljc
;; with minor modifications!
(ns example.coercion
(:require [clojure.walk :as walk]
[clojure.spec.alpha :as s]))
(defonce ^:private registry-ref (atom {}))
;; WARNING - only works if all unqualified kw are unique!!!!
@bhb
bhb / repl.txt
Created September 21, 2018 13:52
Records vs spec for domain modelling - start with `clj -Srepro -Sdeps '{:deps {expound {:mvn/version "0.7.1"}}}'`
Clojure 1.9.0
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (require '[expound.alpha :as expound])
nil
user=> (set! s/*explain-out* (expound/custom-printer {:theme :figwheel-theme :print-specs? false}))
#object[expound.alpha$custom_printer$fn__897 0x534243e4 "expound.alpha$custom_printer$fn__897@534243e4"]
user=> (s/check-asserts true)
true
user=> (defrecord Person [first-name last-name])
@bhb
bhb / repro.clj
Created September 7, 2018 01:43
Changing s/*explain-out* to control spec errors during macro-expansion
(require '[clojure.spec.alpha :as s])
(set! s/*explain-out* (fn [ed] (println "failed")))
(let [x] 1)
;; with org.clojure/spec.alpha {:mvn/version "0.2.168"} :
;; CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
;; failed
;; #:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason "Insufficient input", :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2499 0x749c877b "clojure.spec.alpha$regex_spec_impl$reify__2499@749c877b"], :value ([x] 1), :args ([x] 1)}, compiling:(NO_SOURCE_PATH:3:1)
@bhb
bhb / multimethod_selector.clj
Last active November 13, 2019 10:22 — forked from mtnygard/multimethod_selector.clj
A clojure.spec.gen.alpha generator that picks a multimethod implementation from the known set.
(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
@bhb
bhb / ex.clj
Created August 23, 2018 17:14
Quick hacky idea for generating maps with refs (still has bugs)
(require '[clojure.test.check.generators :as gen2])
(require '[clojure.spec.alpha :as s])
(s/def :aero/path (s/coll-of simple-keyword? :kind vector? :min-count 1 :max-count 3))
(defn aero-map [paths vals-or-refs backups]
(->> (map vector paths vals-or-refs backups)
(reduce
(fn [m [p [t v] [_ backup-v]]]
(case t
@bhb
bhb / gist:910f718e2da57793bc0f5817f006f28a
Created July 17, 2018 13:17
`set!` will apply to threads created within REPL
> clj -Sdeps '{:deps {expound {:mvn/version "0.7.1"}}}'
Clojure 1.9.0
user=> (require '[expound.alpha :as expound] '[clojure.spec.alpha :as s])
nil
user=> ;; default printer is used
user=> (future (s/explain int? "a"))
val: "a" fails predicate: :clojure.spec.alpha/unknown
#object[clojure.core$future_call$reify__8097 0x99a65d3 {:status :ready, :val nil}]
user=> (set! s/*explain-out* expound/printer)
#object[expound.alpha$printer 0x4ad4936c "expound.alpha$printer@4ad4936c"]
@bhb
bhb / gist:c121191c61453bec850a61cc428a109e
Created July 6, 2018 21:19
User-friendly REPL example
clj -Sdeps '{:deps {friendly {:git/url "https://gist.github.com/bhb/2686b023d074ac052dbc21f12f324f18" :sha "c6b0b7cb0a30e2edbf7050c0119ef038cf0f0ac2"}}}' -m friendly
user=> (let [:x 5] x)
Call to clojure.core/let did not conform to spec:
-- Spec failed --------------------
([:x 5] x)
^^
should satisfy
@bhb
bhb / gist:649c46ac6dfa290fa6a62bb96fb66f62
Created July 6, 2018 19:56
Example of a printer that is more suited for instrumentation
user=> (require '[expound.alpha :as expound]
'[clojure.spec.alpha :as s])
nil
user=> (set! s/*explain-out* (expound/custom-printer {:print-specs? false :show-valid-values? true}))
#object[expound.alpha$custom_printer$fn__895 0x38b972d7 "expound.alpha$custom_printer$fn__895@38b972d7"]
user=> (let [{:keys 4} foo] x)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
-- Spec failed --------------------
([{:keys 4} foo] x)
@bhb
bhb / gist:d82fcf0f80f555c28afa8db320be16c8
Created July 6, 2018 15:34
`set!` vs `alter-var-root`
Clojure 1.9.0
user=> (def ^:dynamic *x* "foo")
#'user/*x*
user=> *x*
"foo"
user=> ;; binding changes value
user=> (binding [*x* "bar"] *x*)
"bar"
user=> ;; using set! within binding changes value
user=> (binding [*x* "bar"] (set! *x* "bar") *x*)