Skip to content

Instantly share code, notes, and snippets.

@lfn3
Created August 29, 2016 20:47
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lfn3/0aaf4c420df206484372e9b7bbbe6c6f to your computer and use it in GitHub Desktop.
Save lfn3/0aaf4c420df206484372e9b7bbbe6c6f to your computer and use it in GitHub Desktop.
Validating values put into a channel with clojure spec
(ns channel-of.core
(:require [clojure.spec :as s]
[clojure.core.async :as a]
[clojure.core.async.impl.protocols :as ap]))
(defmacro chan-of [spec & chan-args]
`(let [ch# (a/chan ~@chan-args)]
(reify
ap/ReadPort
(take! [_ fn1-handler#]
(ap/take! ch# fn1-handler#))
ap/WritePort
(put! [_ val# fn1-handler#]
(if (s/valid? ~spec val#)
(ap/put! ch# val# fn1-handler#)
(throw (ex-info (str "Spec failed to validate: "
(s/explain-str ~spec val#))
{:validation-err (s/explain-data ~spec val#)
:val val#})))))))
;; USAGE:
(def test-ch (chan-of int?))
(a/put! test-ch 1) ; => true
(a/put! test-ch "a string") ; => ExceptionInfo Spec failed to validate: val: "a string" fails predicate: :clojure.spec/unknown
; clojure.core/ex-info (core.clj:4725)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment