This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-09
Channels
- # aws (4)
- # bangalore-clj (1)
- # beginners (94)
- # boot (19)
- # cider (42)
- # cljs-dev (21)
- # cljsrn (4)
- # clojure (142)
- # clojure-austin (10)
- # clojure-greece (25)
- # clojure-italy (14)
- # clojure-russia (14)
- # clojure-serbia (13)
- # clojure-sg (6)
- # clojure-spec (74)
- # clojure-uk (69)
- # clojurescript (236)
- # consulting (1)
- # cursive (26)
- # data-science (6)
- # datascript (2)
- # datomic (31)
- # editors (5)
- # emacs (24)
- # funcool (5)
- # hoplon (8)
- # jobs-rus (1)
- # luminus (12)
- # lumo (17)
- # off-topic (90)
- # om (45)
- # onyx (5)
- # pedestal (2)
- # powderkeg (12)
- # protorepl (2)
- # re-frame (30)
- # remote-jobs (2)
- # ring-swagger (17)
- # rum (46)
- # slack-help (1)
- # test-check (2)
- # yada (62)
Would it make sense to have a ^:fdef
(or ^:spec
) meta on fn
to do the :pre/:post automatically from a fdef ? Before you mention instrument, it's not the same (instrument triggers gen).
that would avoid some boilerplate :
(s/fdef ::foo
:args (s/cat :a ::a
:b ::b
:c ::c))
(defn foo
[a b c]
{:pre [(s/assert (:args (s/get-spec ::foo))
[a b c])]
:post [(s/assert (:ret (s/get-spec ::foo))
%)]}
42)
vs
(s/fdef ::foo
:args (s/cat :a ::a
:b ::b
:c ::c))
(defn foo ^:fdef ::foo
[a b c]
42)
the spec and where it's applied is still decoupled, the latter would basically expand into the former (almost, omited the potential :fn part of the spec)
no, not interested in that. first, this re-couples vars and function specs which are intentionally not coupled (and can be created in either order). second, we don’t generally want to enable pre/post checking of specs for performance reasons.
(it doesn't have to use :pre/:post, would open doors to auto conforming via metadata hint etc)
I don’t think Rich has any interest in that
pre/post is toggleable (s/assert as well), but again this would/should be done without these 2 anyway
@alexmiller about ordering I am not sure I follow, if that expands to s/assert calls it wouldn't matter/cause any issue
pre/post effects what ends up in the compiled code (even if toggled off) and thus has a runtime cost
s/assert can actually be omitted from compilation entirely using s/*compile-asserts*
etc
re ordering, right now you create the specs before the functions or after the functions
by having defn rely on the spec, you’ve changed that
if you’re compiling
I don’t know, maybe that would work
aside: the ::foo-like there would be `foo
function specs are named by symbol, not keyword
generally, we don’t think you should be doing this though
that would be handy to be able to reuse specs defined for instrument on live (staging/test) systems without paying the gen cost when that matters
there is no “gen cost”?
the only case like this is with fspec
if that’s a problem for you, then don’t use fspec
and just spec as ifn?
hello all I got the following problem:
clojure
(s/def ::s string?)
(s/def ::g
(s/cat :string ::s
:g (s/* ::g)))
(s/conform ::g '["abc" "abc"]) ; --> ok;
(s/def ::g2
(s/cat :string (s/? ::s)
:g (s/* ::g2)))
(s/conform ::g2 '["abc" "abc"]) ; --> java.lang.StackOverflowError
any ideas?@lambder That recursion will never terminate because (s/? ::s)
may match nothing so once the two "abc"
strings are matched, it will recur forever on the remaining sequence []
@dergutemoritz how do I much the following grammar then?
S -> T R | R
T -> :tag
R -> :foo | :foo R
@lambder That |
in there is probably s/or
Err sorry, it's s/alt
in regex
Everything else is s/cat
Just an educated guess, of course, not sure what grammar notation you're using exactly there
OK then yeah, that should work#
Hm well it's not really BNF though, that doesn't use ->
at least
@dergutemoritz if you wish, please answer it on http://stackoverflow.com/questions/43868064/clojure-spec-conform-throws-stack-overflow-exception you’ll get my upvote
Don't have an SO account
@dergutemoritz many thanks
YW, hope it works out!
suppose I got a spec, (s/def ::foo (s/keys :req-un [::a ::b] :opt-un [::c ::d]))
and a data structure, (def bar {:a 1 :c 3 :d 4 :e 5})
. How do I remove from the bar
all the key-value pairs not explicitly mentioned in the spec and fill in with nils the data that's missing (so, :b nil
and remove :e
)?
spec doesn't do that
I’ve done this:
(in-ns 'clojure.spec)
(defn conform [spec x]
(let [m (clojure.core/or (meta x) {})]
(let [obj (conform* (specize spec) x)]
(cond
(instance? clojure.lang.MapEntry obj) (with-meta (into [] obj) m)
(instance? clojure.lang.IObj obj) (with-meta obj m)
:else obj))))
@dergutemoritz I got better answer by @flowthing if you are interested. http://stackoverflow.com/a/43869208/135892 thanks to @alexmiller
Is it possible to ‘tap’ into a protocol method. I’d like to have ‘around’ wrapper for all such method calls.
e.g there is a protocol clojure.spec.Spec
which has conform*
method defined.
Some of the conform*
implementations call conform*
recursively. I’d like to wrap my logic around each such call.
my monkey patch is :
(in-ns 'clojure.spec)
(defn conform [spec x]
(let [m (clojure.core/or (meta x) {})]
(let [obj (conform* (specize spec) x)]
(cond
(instance? clojure.lang.MapEntry obj) (with-meta (into [] obj) m)
(instance? clojure.lang.IObj obj) (with-meta obj m)
:else obj))))
in short, no and anything touching these impl details stands a good chance of being broken later
@alexmiller yes, i think so too. Any idea why conform*
implementations aren’t calling conform
? performance?
@lambder Err I just realized that the grammar you pasted is not equivalent to what you were trying to express in spec - according to that, :tag
is only allowed as the first element of the whole sequence and then only :foo
s are allowed (because R
recurs on itself, not on S
). Is that what you intended?
but thanks to http://stackoverflow.com/a/43869208/135892 now I know how to express this kind of grammers in spec
@lambder AFAIUI that's more complicated than necessary. Doesn't something like (s/def ::g (s/+ (s/cat :tag (s/? ::tag) :val (s/alt :number ::n :string ::s))))
capture what you want to do much neater + give you a more convenient result structure to work with?
Might be misinterpreting your use case, of course. Anyhow, gotta run. Cheers
Is there a way to define newtype's in spec? e.g. specialise a Long to an AccountId or a ProductId. I'm pretty sure there's not, but thought I'd ask in case.
@danielcompton seems like the spec name itself is that information
Let's say I have a function that gets a product (get-product product-id)
. If the product-id and account-id are both Longs, nothing stops me from passing it (get-product account-id)
I solve this by creating :account/minimal
as (s/keys :req [:account/id] :opt [ all the other stuff])
when really necessary
but if you ever need to extract and pass around :account/id
by itself, then you can't guarantee that that's what the functions are taking?