This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-04
Channels
- # architecture (5)
- # aws (11)
- # aws-lambda (1)
- # beginners (108)
- # boot (11)
- # cider (37)
- # clara (19)
- # cljsrn (72)
- # clojure (170)
- # clojure-austin (2)
- # clojure-dev (1)
- # clojure-dusseldorf (2)
- # clojure-italy (1)
- # clojure-spec (41)
- # clojure-uk (24)
- # clojurescript (113)
- # component (2)
- # core-async (29)
- # cursive (9)
- # data-science (5)
- # datomic (72)
- # docs (23)
- # duct (61)
- # editors (1)
- # emacs (1)
- # events (5)
- # fulcro (77)
- # graphql (2)
- # hoplon (4)
- # jobs (3)
- # jobs-discuss (16)
- # leiningen (5)
- # off-topic (94)
- # onyx (37)
- # precept (5)
- # re-frame (17)
- # reagent (11)
- # shadow-cljs (18)
- # spacemacs (107)
- # specter (3)
- # unrepl (64)
- # yada (1)
I have the following spec:
(s/cat :binding (s/? (s/cat :binding-var ::variable-name
:sep #{'<-}))
:fact-type any?
:destructured-fact (s/? ::destructured)
:expressions (s/* any?))
This is horribly ambiguous as written, due to the use of any?
and repeated/optional elements.
I’d like to make the first s/?
greedy, so to say if it’s possible to match the :binding
part then that’s what should happen.
The only alternative I can think of is to do this, taking advantage of ordering precedence for alternates:
(s/or
:with-binding (s/cat :binding-var ::variable-name
:sep #{'<-}
:fact-type any?
:destructured-fact (s/? ::destructured)
:expressions (s/* any?))
:no-binding (s/cat :fact-type any?
:destructured-fact (s/? ::destructured)
:expressions (s/* any?)))
In short, no. The way the regex derivative stuff works is kind of doing all the options in parallel
FWIW other regex parallel implementations allow this even though they work in lockstep with no backtracking.
I think it would be worth specifying in the doc if ops like ?
and *
are greedy or not - it’s not mentioned right now and is useful information in ambiguous cases.
I don’t know that I understand what you’re trying to spec well enough but the latter seems more readable to me
One thing I’ve found is that spec’ing a dsl is a pretty good way to judge how good your dsl is :)
> One thing I’ve found is that spec’ing a dsl is a pretty good way to judge how good your dsl is :) Yeah, in the case of Clara, there is a bit too much ambiguity in this case I’d say. Have to figure out a way to tighten it down a bit perhaps. Spec to the rescue.
I seem to recall that someone published a repository with some specs for core functions (beyond what is currently included in https://github.com/clojure/core.specs.alpha), but now I can’t find it. Anyone else remember this?
I realize that these specs may be incomplete or buggy, and that’s OK for my use case. This is just for toying around with instrumentation.
Oh, nevermind, my fourth google search finally found it https://github.com/leifp/spec-play
There's also this one: https://github.com/tirkarthi/respec Don't know how it compares to the one you mentioned
@andre.stylianos Awesome, thanks!
the repos I’ve looked at were both mostly wrong and not very good examples of specs, so ymmv
@alexmiller Good to know. I’m not that concerned about accuracy for this case, but if they are not well-written specs, that’s more of an issue, since I’m using these as a temporary proxy for the real clojure.core specs
I should clarify: I’m not worried about completeness in the sense that if, say, some functions are missing specs for certain less common arities, that’s OK. If the specs are just buggy in general then that would cause an issue.
from what I’ve looked at, the specs are wrong, as in will both allow bad things and reject good things
and most of them spec a bunch of things that instrument won’t work with (inline functions and functions with primitive args), which is not bad, but also not useful
Gotcha. Yeah, for my case, rejecting good things will cause issues. I’ll take a look.
> bunch of things that instrument won’t work with (inline functions and functions with primitive args) I’m afraid I don’t understand. Can you expand on this a little?
instrument currently doesn’t work with: functions taking/returning primitives (fixable), inlines, multimethods (fixable), and protocols
so spec’ing +
will buy you nothing for example
but it’s not harmful and does get included in docs, which might be valuable in and of itself
@seancorfield @alexmiller Ah, thanks. I did not know about that. If this works, I’ll be using instrumentation in CLJS, so presumably the primitive issue will be different
Oh yeah, I’m talking Clojure
Well, I didn’t mention the CLJS part before 🙂 and in any case, those specs are in CLJ, so I can see why you thought CLJ (I’ll need to copy them into a cljs file if I want to use them).
Why is this valid?
(s/def ::cat (s/cat :a keyword? :b any?))
(s/def ::foo (s/coll-of (s/spec ::cat)))
(s/valid? ::foo {:a "a"})
=> true