-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conform strings while leaving everything else unformed #65
Comments
Hi. And thanks for the detailed description. The conform+unform is the way to do it with spec, not sure there is any other way to do it. For most Specs, the unform is just no-op, so should be fast, despite it requires second walk over the value. I would add a conform-unform fn into the client project. You could verify that form Cognitect people, at least Alex is hanging on #clojure-spec in Slack. One thing that would help a bit is to resolve #60 - enum types could be extracted automatically (mostly homogenous). We are btw using Transit in clj<->cljs remoting, which retains types. |
Hey, thanks for the reply.
One thing that has occurred to me as potentially useful, in spec-tools, would be to extend the visitor pattern implementation to allow for visiting spec'd values. With this, spec-tools could provide a
We're using EDN for our transit data, between cljs and clj. This loss of data is actually happening when giving cljs values to ReactNative, through Reagent. I didn't dig into the details in the first post, since this sort of thing can come up in various ways when JSON and JS are involved. |
IIRC this was basically my suggestion for implementing custom coercions. We ended up doing the dynamic variable thing because it was much simpler to bolt it to clojure.spec's What you suggest would be an important building block for this, so I'm definitely open to it. What do you think, @ikitommi? |
Good discussion. I did a spike on holidays on adding coercion support to the spec itself, found here: clojure/spec.alpha#1. Waiting for comments on that via CLJ-2116 on Jira. I'm always open for better ways on doing this, if you have time, a spike/gist/PR would be most welcome. Performance is also a value, now the spec conform is quite fast as it's walking through the protocol methods (instead of generic tree walking). Initially was about to add |
Did a perf test on the conform-unform. Actually, the unform for maps is dead slow. One would be to have the spec Any progress / ideas for this (on the spec-tools side)? |
Gah. We not only use this (conform + unform) for our ReactNative stuff, as I mentioned in an earlier comment, but now also for all of our Firebase Real-Time Database data. I took a look at your PR and something like that would be perfect; I'm just not optimistic for it catching on with the Clojure team. Is this something which can only be addressed in From what it sounds like, the coercion @miikka brought up would essentially be a reimplementation of |
It was just simpler to do the dynamic variable thing, esp. since clojure.spec was/is a bit of moving target. We didn't want to re-implement |
It's impossible implement the better We could read the type from It seems that Rich hasn't assessed the CLJ-2116, so motivation to write a better version is not that hight at moment. I could draft that thou. |
Tommi, all the information you need is in Seriously, |
Funny :) Ok, let's thing about the
The good:
Downsides:
Did I miss something? Some better ways to do this? Want to implement this? And of course, right place to implement this would in
cheers, Tommi |
Oh, forgot. Specs have a lot of internal state that is not visible outside of the Protocol. To re-implement coercion, we would have to copy that state mungling to spec-tools too.
A backwards compatible fork of |
Now that's an idea. As you described in detail, all of this could make it into spec-tools. A fair amount would need to be duplicated from clojure.spec though, simply because Cognitect isn't interested in these transformations. Doing this in spec-toolsPros
Cons
Forking clojure.specPros
Cons
If there were only one clojure.spec repo, for both Clojure and ClojureScript, I'd suggest going the forking route. Dealing with those two mostly-duplicated repos is a real pain though, as I've seen with orchestra. |
clojure.spec consists of two parts:
A part of what spec-tools does is ditching the language -- see e.g. data specs which replace it with a Schema-like language. The other part, which we're now talking about, is ditching the library, since it's not really suitable for high-performance coercions. I'm inclined to ask if there's any point in this project. If the Schema language and the Schema library are better for e.g. libraries like ring-swagger, why bother with clojure.spec? |
Awesome. Thanks, @ikitommi. One addition which may be helpful is to illustrate an example usage of |
After a year of waiting the 2251, just hacked together an minimalistic external walker. It can be used to build a simple coercion which does just coercion without validation (just like spec-coerce): walker sees both the spec and the value. Is not optimized for perf and can only walk over simple specs - re-parsing regexp specs would mean to rewrite most of the spec. But, there will be (require '[clojure.spec.alpha :as s])
(require '[spec-tools.core :as st])
(require '[clojure.test :refer :all])
(s/def ::c1 int?)
(s/def ::c2 keyword?)
(let [spec (s/nilable
(s/nilable
(s/coll-of
(s/or :keys (s/keys :req-un [::c1])
:ks (s/coll-of (s/and int?)))
:into #{})))
value [{:c1 "1" ::c2 "kikka"} {:c1 true} [1 "2" "invalid" 3]]]
(is (= #{{:c1 1, ::c2 :kikka} {:c1 true} [1 2 "invalid" 3]}
(st/coerce spec value st/string-transformer)))
(is (= #{{:c1 "1", ::c2 :kikka} {:c1 true} [1 "2" "invalid" 3]}
(st/coerce spec value st/json-transformer))))
; true |
0.8.0-SNAPSHOT |
This is either a question of a feature request, depending on whether or not it's already available. Based on what I've read from the docs, this hasn't been mentioned.
Use case
I'm working with ClojureScript, where my map values which are keyword are often turned into strings against my will. In hopes of fighting this problem, I've been trying out spec-tools. He's an example of the conforming I'm doing:
Desired functionality
As shown above, this conforming is sweeet. Unfortunately, it also does the normal conforming stuff, like turning
s/or
ands/alt
into their named pairs. Here's an example, based on the same REPL session above.As soon as
::spam
has an alternative, the value I get back is less than ideal.Short-term work-around
For now, I've been subsequently unforming my conform, which adds the keywords in the right spot, but removes the named pairs. As you can imagine, for performance, efficiency, and cleanliness, this isn't ideal. Here's an example, again, based on the above session:
Long-term solution
As this is a common problem in both ClojureScript and Clojure code working with JSON and other formats which don't support EDN keywords, a cleaner solution would be preferred. I'd be happy to discuss more.
Thanks!
The text was updated successfully, but these errors were encountered: