This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-22
Channels
- # beginners (104)
- # bitcoin (1)
- # boot (5)
- # clara (3)
- # cljs-dev (14)
- # cljsjs (5)
- # cljsrn (1)
- # clojure (242)
- # clojure-italy (17)
- # clojure-news (13)
- # clojure-norway (3)
- # clojure-russia (101)
- # clojure-spec (41)
- # clojure-uk (87)
- # clojurescript (38)
- # core-async (38)
- # cursive (6)
- # datomic (11)
- # defnpodcast (3)
- # docs (14)
- # editors (8)
- # events (1)
- # fulcro (7)
- # hoplon (25)
- # leiningen (4)
- # luminus (7)
- # off-topic (25)
- # onyx (1)
- # portkey (14)
- # random (1)
- # re-frame (7)
- # reagent (4)
- # rum (4)
- # schema (8)
- # shadow-cljs (257)
- # spacemacs (10)
- # specter (4)
- # unrepl (3)
- # yada (1)
Given a fn like (defn foobar ([a] (inc a)) ([a b] (str a b)))
where arity 1 expects a number and, let's say, arity 2 expects two strings, can I spec this so that arity 1 doesn't accept a single string?
Everywhere I see people spec'ing multiple arities, they'll just use s/or
. That leaves all sorts of open holes.
I'd see something like this: (s/fdef foobar :args (s/cat :a (s/or :int integer? :str string?) :b (s/? integer?)))
(s/fdef foobar :args (s/or :one (s/cat :a number?) :two (s/cat :a string? :b string?)))
Damnit, that worked perfectly. Cheers, @seancorfield. I think I had tried s/alt
there, with two s/cats
, but it failed.
s/alt
will alternate multiple sequence regexes <-- this is poorly worded but I'm not quite sure how to describe its interaction with s/cat
This would be a good thing to have in the spec guide, I think; multiple arities aren't covered at all.
It probably doesn't help that the docstrings for s/alt
and s/or
look so similar. Seems to be a common point of confusion.
I just tried it with s/alt
in place of s/or
and it worked -- but the spec failure you get for (foobar "a")
is different...
boot.user=> (foobar "a")
clojure.lang.ExceptionInfo: Call to #'boot.user/foobar did not conform to spec:
In: [0] val: "a" fails at: [:args :one :a] predicate: number?
val: () fails at: [:args :two :b] predicate: string?, Insufficient input
:clojure.spec.alpha/spec #object[clojure.spec.alpha$or_spec_impl$reify__810 0x55365ffb "clojure.spec.alpha$or_spec_impl$reify__810@55365ffb"]
:clojure.spec.alpha/value ("a")
:clojure.spec.alpha/args ("a")
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file nil, :line 1, :var-scope boot.user/eval1830}
compared to boot.user=> (foobar "a")
clojure.lang.ExceptionInfo: Call to #'boot.user/foobar did not conform to spec:
val: () fails at: [:args] predicate: (alt :two (cat :a string? :b string?)), Insufficient input
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x373ea576 "clojure.spec.alpha$regex_spec_impl$reify__1200@373ea576"]
:clojure.spec.alpha/value ("a")
:clojure.spec.alpha/args ("a")
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file nil, :line 1, :var-scope boot.user/eval1846}
In the first case, it fails to match :args :one :a
because "a"
is not a number?
and it also fails to match :args :two :b
because only one string was provided.
In the second case, it only reports the failure to match on alt :two
(again, because only one string was provided).
The spec I used was (s/fdef foobar :args (s/alt :one (s/cat :a number?) :two (s/cat :a string? :b string?)))
Ah, I was getting the second one, but I was also likely testing with invalid inputs and ... bah, I don't remember. Awesome to see it works well; thanks again.
Not having to calculate the various alternations between arities for use with s/or
is going to make my macro writing significantly simpler as well.
Is there a good spec floating around for specs themselves? They can be ifn?
but also things like s/coll-of
return something else. I've also tried s/spec?
.
For spec forms that is
Currently spec instances should just be considered to be opaque and respond to true for s/spec?
That would be a good question for Alex when he's around tomorrow @jeaye
I can’t seem to get my mutimethods to become intstrumented. Anyone else also having this issue?
Multimethods are weird, one of those things I sometimes restart my repl for and it just works.
@vikeri see above (hope the link works)
@andrewmcveigh Ok thanks!
@gfredericks is it possible to write a generator that continues to generate until the sum of an operation on the generated stuff meets a condition?
for instance generate integers until their sum is 5
@richiardiandrea that doesn't make a lot of sense, since there's a almost unlimited set of numbers that would sum up to 5
you want a collection of integers in particular?
right, let's say I restrict the domain
and you want the sum to be =5, or <=5?
I see now the reason of this question, I am basically now generating a list of things such that their sum <= total randomly, if < then the last element is manually crafted
yeah, that's definitely a legit way to do it
basically I would want to have a such-that
, but where I accumulate results first, then I apply pred
on the result
one idea is to generate larger sequences and fmap
it to the largest prefix that meets your criteria
would that be sufficient?
uhm, let me try that, I will be back with the result 😄