This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-03
Channels
- # aleph (5)
- # announcements (4)
- # babashka (2)
- # beginners (52)
- # calva (13)
- # cider (60)
- # clj-kondo (91)
- # cljsrn (6)
- # clojure (93)
- # clojure-brasil (2)
- # clojure-dev (37)
- # clojure-europe (5)
- # clojure-italy (7)
- # clojure-nl (8)
- # clojure-norway (1)
- # clojure-sg (1)
- # clojure-spec (115)
- # clojure-uk (31)
- # clojurescript (32)
- # cursive (35)
- # data-science (4)
- # datascript (3)
- # datomic (29)
- # emacs (8)
- # events (1)
- # figwheel (1)
- # funcool (2)
- # graalvm (2)
- # joker (12)
- # kaocha (4)
- # lein-figwheel (1)
- # leiningen (34)
- # malli (7)
- # off-topic (4)
- # overtone (1)
- # parinfer (2)
- # pathom (5)
- # quil (1)
- # re-frame (12)
- # reagent (2)
- # shadow-cljs (7)
- # spacemacs (6)
- # sql (8)
- # tools-deps (63)
- # vim (24)
Well, we're just going to disagree on how clear we think the Clojure/core team have been on that... ¯\(ツ)/¯
I've added a warning to the readme of both core.specs.alpha and spec.alpha
Problem solved! 🙂
@alexmiller THANK YOU!
If you have another suggestion of how to signal this, please let me know
sorry it wasn't clear
I think making alpha ok with breaking stuff is fine, with the caveat that having something in alpha for years and deps of official releases is admittedly weak sauce
yet, that's where we are
I have a burning desire to move these libs out of alpha and stabilize
Speaking from my experience with the greek letter style namespaces, its been incredibly liberating to not have to worry about breaking users.
and as fair warning, core.specs.alpha is eventually going to get updated to depend on spec-alpha2 (or some future non-alpha variant) and will necessarily break again. But on the upside, these will be new names, not breaking versions of old names.
Is there an appropriate place to discuss this or get an explanation? It doesn’t seem like a necessary requirement for spec alpha to depend on any other version of spec.
Put another way: is there a path forward that doesn’t cause breakage? Breakage should be taken seriously and avoided at all costs. It takes real time and effort on behalf of users to deal with it.
We have had some discussion about it but are deferring until later the full analysis of what we will do for migration. Most likely, there will be a new lib (probably core.specs
) with new namespaces and new (spec 2) specs. There are a number of possible paths to continuing to support spec 1 specs (via some adapters possibly) and many choices about to what extent they are supported. Exploring this in full depth is more than I'm going to do in this slack thread.
You're preaching to the minister here on breakage, but as an alpha library the plan was always to ultimately be replaced and we've been pretty vocal about that from the start.
N months from now, Rich and I will go through a design process to try to flush out all the questions and answers around this
how and what kind of feedback we'll need at that point I'll defer to that point
what the world will look like then, I have no idea so I'm not going to worry about it now
clojure.spec.alpha
-> clojure.spec-alpha2
has some major breakage for users who choose to migrate. Most mainstream stuff is unchanged but there's a lot of "dragons" if you've ventured off that path 🙂
Its been incredibly liberating for me to be able to make new versions of my library without worrying about breaking users or, worse, stagnating.
Maybe I took what Rich said to the extreme but, in practice, what I’ve come to discover is that strive for a “stable version” is just a withdrawal symptom of breaking away from a bad versioning habit and way of thinking about a project.
Like, it no longer bothers me that the next version of Meander, when I get to it, will live at meander/zeta
. I don’t care that I can’t (:require [meander.core :as m])
. (:require [meander.zeta :as m])
is fine.
The whole idea of a “stable version” is odd to me when we all know the only thing we can rely on as software developers is that things are rarely, if ever, stable.
well, you will have that
but at the point we go there, we will try to maintain only additive changes after that point
it's not sem ver
it's an increasing set of numbers that make only additions
I believe we have that discipline :)
and will submit the rest of clojure as evidence :)
because supporting an ever changing set of namespaces across versions is irritating?
there's a balance of tensions here
The question is “how do you know you’re at a stable point where its possible to only sustain the software on discipline you can be sure you have?”
in general, I would rather just bump versions than bump versions AND update the namespaces in all my code
In principal you can do that already with any artifact that uses SemVer in honestly and never has a major version bump.
I'm going to just say experience. but changing to new namespaces or even new lib names is not an option that's lost - we can always do that if needed
I'm suggesting a small thing for users while still retaining the option to do the big thing for users
that seems better regardless
Well, Alex, I’m not going anywhere anytime soon as far as I can tell so I’m looking forward to seeing where this goes. 🙂
I gotta go be a dad but, again, thanks @alexmiller for making that change to the README.
ditto on dad time
Current spec alpha has a function s/merge
which works like s/and
in that it will only conform the last spec. I am wondering if spec-tools
coercion suffers from same problem?
@roklenarcic there is spec-tools.core/merge
> .. that selects only the specced keys from each conformed result, then merges those results onto the original input. This avoids overwriting conformed values with unconformed values while preserving all unspecced keys of the input. Fixes #90. By Arttu Kaipiainen.
Cool thanks
does it work this way with s/conform or only with coerce?
Hm, ended up not using coerce, because it doesn't use any conforms defined in specs.
there is also decode
, which does both. It's quite messy to try to implement transforming from a 3rd party library. https://clojure.atlassian.net/plugins/servlet/mobile?originPath=%2Fbrowse%2FCLJ-2251#issue/CLJ-2251 would make things better.
https://github.com/metosin/spec-tools/blob/master/src/spec_tools/core.cljc#L232-L248
@alexmiller just like to say thanks for all the work you and the team have done and continue to do with Spec. It is much appreciated. Thank you.
Hi all. I'm trying out spec alpha2. I noticed I accidentally forgot to include a key in my schema, but s/select does not seem to validate that the key exists in the schema.
(s/def ::first string?)
(s/def ::last string?)
(s/def ::user (s/schema [::first ::last]))
; Should the select blow up? email is not in spec
(s/def ::create-user (s/select ::user [::last ::email]))
s/schema and s/select both support open maps (extra keys are ok), just like s/keys
I thought (s/select ::user [::last ::email]))
is specifically saying I'm choosing to require ::email from the ::user schema
whether you should get some feedback if s/select requires things not in the schema is a reasonable question, and not something we've talked about
Without any validation it seems like I don't need the schema at all except for documentation purposes
several things - 1) supports gen in both schema and select, 2) basis for closed spec checking if you want to do that, 3) yes, docs
(s/explain ::create-user {::last "Smith"})
#:user{:last "Smith"} - failed: (fn [m] (contains? m :user/email)) spec: :user/create-user
^^ Validates email perfectly fineOne question that came to my mind yesterday as I worked through getting our entire code base switched to the latest Spec 2 and our full test suite passing: how will folks deal with the world when they want to use Spec 2 but they rely on a chain of dependencies where one of the downstream libs still depends on Spec 1. https://github.com/cognitect-labs/anomalies/blob/master/src/cognitect/anomalies.cljc is a good example: very small, focused lib that defines Spec 1 specs and could be depended on by any number of libs in your tool chain.
To get our code base passing all its tests, I had to essentially recreate Anomalies' specs in my code, I had to create Spec 2 compatible versions of expectations.clojure.test
(one I maintain), and worldsingles/web-specs
(work maintains), since those are downstream dependencies using Spec 1.
@alexmiller If Spec 2 becomes clojure.spec
(no alpha), how will folks deal with a mixed Spec 1 (alpha) / Spec 2 (contrib) code base?
In particular, in our case, we create specs in our own code (Spec 1 on master, Spec 2 on a branch) that incorporate the specs from Anomalies -- which I suspect is going to be a fairly common situation that folks get themselves into...
I think it's possible to build an adapter layer from spec 1 to spec 2, but we're going to push off answering these questions till we have something good enough to migrate to
Fair enough 🙂 Is there a specific outline of work left to do on Spec 2 at this point? Or is even that aspect not "baked" yet?
there's a rough list at the end of my clojutre talk
* More on map forms
* Function specs, ret/fn specs, defn
* Metadata / doc strings
* Open enumerated sets
* Spec traversal
that doesn't all necessarily have to be done to be at a release point if we feel it's additive from that point
so the actual list may be shorter (or longer) but certainly nailing down 1,2, and probably 4
Ah, and I just watched that the other day and forgot about that list. Sorry.
What do you mean by "Open enumerated sets" in that context?
And "More on map forms" means the unqualified, inline s/schema
definitions?
re open enumerated sets - using a set as a predicate #{:red :green :blue} is a different form of "closed" predicate. Often you want to say "these constants", but also other things later
"more on map forms" = more work on the "map" form of specs
as the maps currently in there are a first pass and we will likely change the form of some of them and probably automate the form<->map definition somehow
Ah, the "AST" stuff... OK.
Re: enumerated sets. That sounds interesting. I'm not sure I can come up with a use case right away tho', but I can see how set literals are currently "closed".
Anyone know of a library that lets you strip extra keys of a multi-spec/parameterized map? For example, if a map with :type
set to :a
requires keys :a1
and :a2
, any additional keys would be removed.
You can use select-keys, but the problem is that you define the key set in two places. I had a similar problem and defined the schema as data {:req [::a1 ::a2] :opt [::a3]}
. From there, I use the data to generate the spec and the keyset.
spec-tools can do that (in case I understand correctly): https://github.com/metosin/spec-tools/blob/master/docs/01_coercion.md#spec-coercion
It needs to be a bit smarter than that because multi-spec is used. I’d only like to select the keys that the multi-spec for a particular dispatch defines.
Hello 🙂 Possibly a silly question but what is the recommended way of working with specs whose data they model I want to serialise and deserialise to JSON with unnamespaced keys?
so, in clojure the keys should be namespaced (since, as far as I understand, that’s the only way to work with spec), but in JSON they should not, and when deserialising JSON into a clojure datastructure I want to automatically namespace the keys based on some spec
seems like https://github.com/metosin/spec-tools/blob/master/docs/01_coercion.md is what I am looking for?
:req-un
and :opt-un
are for unqualified key names -- but let you associate qualifiers for the matching spec names.
(s/def :foo/bar string?)
(s/def :foo/map (s/keys :req-un [:foo/bar]))
(s/def :quux/bar int?)
(s/def :quux/map (s/keys :req-un [:quux/bar]))
;; so you have have {:bar "s"} in one context and {:bar 42} in a different context
Does that help @hmaurer?@seancorfield thanks! I think it does; initially I was thinking I would want some sort of way to deserialise {"bar": 42}
(json) into something like {:foo/bar 42}
in a spec-driven way, but I could just use req-un
and have unqualified keywords everywhere
Yeah, I'm not sure what to recommend for switching between "JSON" style maps and "internal" (qualified) maps. I think a lot of that is context-dependent / application-dependent so I'm not sure there's a generic approach that suits everyone.
Given the specs, you can always get the form
of the spec and get the list(s) of keywords used in the spec and you could create a generic way to call clojure.set/rename-keys
or simply process the (JSON) map to qualify the keys yourself. Much will depend on exactly what your application needs and why you need to perform that transformation.