This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-07-01
Channels
- # admin-announcements (2)
- # aleph (1)
- # aws-lambda (14)
- # beginners (6)
- # boot (34)
- # carry (71)
- # cider (8)
- # cljs-dev (3)
- # cljsjs (3)
- # clojure (40)
- # clojure-belgium (1)
- # clojure-greece (182)
- # clojure-mexico (1)
- # clojure-poland (8)
- # clojure-quebec (1)
- # clojure-russia (72)
- # clojure-spec (30)
- # clojure-uk (120)
- # clojurescript (62)
- # cursive (3)
- # datomic (17)
- # euroclojure (5)
- # hoplon (26)
- # keechma (6)
- # mount (3)
- # off-topic (2)
- # om (5)
- # onyx (4)
- # other-languages (3)
- # parinfer (2)
- # pedestal (2)
- # planck (30)
- # re-frame (81)
- # reagent (31)
- # spacemacs (7)
- # spirituality-ethics (21)
- # testing (10)
- # untangled (80)
I’m working with instants and ended up with this code:
(defn years-ago
"Given a number of years, return an Instant that long ago."
[y]
(-> (LocalDate/now) (.minusYears y) .atStartOfDay (.atOffset ZoneOffset/UTC) .toInstant))
(defn age-18-120?
"Given an Instant, return true if it represents a date of birth such
that someone would be between 18 and 120 years old."
[i]
(s/inst-in-range? (years-ago 120) (years-ago 18) i))
(s/def ::date-of-birth (s/with-gen age-18-120?
(fn [] (s/gen (s/inst-in (years-ago 120) (years-ago 18))))))
Could this be done more cleanly? (without the duplication of the range of years)(s/def ::age-18-120? (s/inst-in (years-ago 120) (years-ago 18)))
=> :kafka-google-connector.runner/age-18-120?
(defn age-18-120? [x] (s/valid? ::age-18-120? x))
=> #'kafka-google-connector.runner/age-18-120?
(s/def ::date-of-birth ::age-18-120?)
=> :kafka-google-connector.runner/date-of-birth
(s/exercise ::date-of-birth 1)
=> ([#inst"1970-01-01T00:00:00.000-00:00" #inst"1970-01-01T00:00:00.000-00:00"])
though the age-18-120? fn seems totally redundant at that point, but if you still wanted it
No, because the years-ago
calls must happen when the predicate is applied, not just once at compile time.
And I'm assuming the with-gen
generator-returning fn is called each whenever the spec is exercised / test-gen'd but that's not really as important since tests are short-lived, whereas the spec has to be long-lived and check the correct range of dob each time it's conformed / used for validation.
@seancorfield: could "now" be part of the data structure you spec/validate? that makes it a simple input rather than implied context.
Will it make sense to update defn to allow a spec to be provided as metadata? seems like it could overlap with pre/post...
(defn option-match
"Default search for local datasource: case-insensitive substring match"
[simple? option query]
{:args (s/cat :simple? boolean? :option ::option :query string?)}
No, we won't be doing that
So, specs can also be used to convert invalid data into valid data? I’m reading this…
conformer
macro
Usage: (conformer f)
(conformer f unf)
takes a predicate function with the semantics of conform i.e. it should return either a
(possibly converted) value or :clojure.spec/invalid, and returns a
spec that uses it as a predicate/conformer. Optionally takes a
second fn that does unform of result of first
So how do you use the feature to get the response (possibly converted)
?@seantempesta: you have to provide a function that returns :invalid or a result that is the converted value
holy crap, this is great!
thanks @bhauman!
would love to see this answered @alexmiller https://clojurians.slack.com/files/glv/F1MQPJBQT/Specifying_an____annotated_value_map_.md
@ghadi: one simple option that I see is to move the cached data to the map meta-data, this way the map validation can stay simple
But I’d like to validate the cached data as well. For purposes of the code, it’s not valid if those keys aren’t there.
@glv: I had a different idea, what you think on this:
here, I used a conformer
to remove the namespaced keys before doing the map validation, but checking the keys before doing it
this way all namespaced keys will be validated, then removed just to check the rest of the map
@olivergeorge: Interesting idea… The data structure comes from the database and we already decorate it with some computed fields that are transient (short-lived) so adding a current timestamp to the data wouldn’t be a hardship.
@ghadi: sorry, moving today!
I’m trying to use spec-test/test in my clojure.test tests (that was a lot of test :)). When I try to realize the result of test I get the following exception
java.lang.ClassCastException: clojure.lang.AFunction$1 cannot be cast to clojure.lang.MultiFn, compiling:(clojure/test/check/clojure_test.cljc:95:1)
@alexmiller: good luck!
@alexmiller no worries … whenever things calm down is fine.