This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-10
Channels
- # announcements (4)
- # beginners (116)
- # boot (4)
- # calva (63)
- # cider (8)
- # clara (20)
- # cljdoc (10)
- # cljsrn (69)
- # clojure (115)
- # clojure-austin (1)
- # clojure-dev (4)
- # clojure-finland (1)
- # clojure-italy (3)
- # clojure-nl (6)
- # clojure-russia (10)
- # clojure-uk (84)
- # clojurescript (28)
- # cursive (14)
- # data-science (1)
- # datascript (1)
- # datomic (11)
- # duct (3)
- # emacs (13)
- # figwheel-main (11)
- # fulcro (4)
- # graphql (6)
- # jackdaw (2)
- # jobs (23)
- # jobs-rus (1)
- # kaocha (11)
- # lein-figwheel (13)
- # leiningen (55)
- # luminus (14)
- # lumo (22)
- # off-topic (121)
- # pathom (19)
- # re-frame (6)
- # reagent (3)
- # reitit (22)
- # remote-jobs (10)
- # ring-swagger (1)
- # shadow-cljs (67)
- # slack-help (5)
- # spacemacs (1)
- # sql (18)
- # vim (28)
- # yada (2)
wrote an issue about how leiningen merges maps - can’t remove values from those. Does anyone know/remember if there was a reason for this? or just a bug? https://github.com/technomancy/leiningen/issues/2556
@ikitommi I think I’ve seen nested meta supporting structures used instead for those cases before so the replace metadata worked.
But yeah, offhand I don’t know why the behavior is that way regarding nil. I guess sort of makes sense if that’s the merge semantic you were going for in some situations. Merging as combining instead of overwriting.
I think it would be a small change to check if the key exists and value is nil, and it should override the value to nil. Like it works with non-collections already. There are at least three copies of meta-merge, would not want to make a fourth copy with just this change.
Using it in all projects, really like the way it allows the user be in charge how things are merged.
@ikitommi I agree it’d be nice to do what you want in some cases. I don’t think it auto handling nil that way makes sense though.
I think there are cases where you’d not want nil to wipe out other values. Instead “combine” them
Maybe when the merging values are non-collections it may be ok. But that may be a weird stipulation.
I often wish meta merging let you use a placeholder value to wrap a value when you needed to add metadata like :replace to something that doesn’t support it
My use case is with the #reitit routing library. I use meta-merge to accumulate route data from a route tree into endpoints. It works like a charm in all cases but in the one where I one want’s to set some default in the top-level and override (remove) that default somewhere along the way. The common case:
(def router
(r/router
["/api" {:interceptors [::api]}
["/ping" ::ping]
["/admin" {:roles #{:admin}}
["/users" ::users]
["/db" {:interceptors [::db]
:roles ^:replace #{:db-admin}}]]]))
, get’s expanded (and meta-merged) into:
(r/routes router)
; [["/api/ping" {:interceptors [::api]
; :name :user/ping}]
; ["/api/admin/users" {:interceptors [::api]
; :roles #{:admin}
; :name ::users} nil]
; ["/api/admin/db" {:interceptors [::api ::db]
; :roles #{:db-admin}}]]
but adding a content-negotiation is done my setting a :muuntaja
key with a instance (non-collection) as a value, preferaby to the root, effecting all routes. With the current meta-merge impl, it’s impossible to unset the value without some marker values like false
etc. The thing that meta-merge handles explicit nil
differently than the clojure.core/merge
makes me think it’s a bug.
If this would be fixed in Leiningen, the change would be mirrored to the meta-merge library I’m using (https://github.com/weavejester/meta-merge). Another option is to make a friendly copy and name it somethin like ctrl-merge
. There is already a bit-different duct-meta-merge around (https://github.com/duct-framework/core/blob/master/src/duct/core/merge.clj).
but I’m saying the :replace
metadata already exists for the concept of “replacing”/overwriting
the downfall to it is that it only works on things that support metadata - like not on nil
right?
Was it’d be nice if the meta-merge transparently supported a “special wrapper type” that could take metadata for things that cannot have metadata
Then the same :replace
mechanism could be used in any case - as well as :displace
and whatever else
hmm. I think the fix would be generic if it checked the map entry - if that exists and the value is not a collection, it would override.
as it works already with all non-collections, like (meta-merge {:a 1} {:a 2}) ; => {:a 2})
but you want nil to override, not sure all cases would want that - maybe you could justify as that’s just what non-collections do
I don’t think it’s that uncommon for people to put :x nil
in a map instead of not adding :x
at all
in clj I find, you often have to go out of your way to not put the key in the map - it’s uglier
so in those cases, if that’s automatically happening, and it gets in front of a meta-merge - with your change, it’ll start wiping out other values instead of being ignored
What I mean here:
> in clj I find, you often have to go out of your way to not put the key in the map - it’s uglier
(assoc m :x <don't know if I have this>)
is commonly done, when really
(cond-> m (some? <don't know if I have this>) (assoc :x <don't know if I have this>))
would be more appropriate
> so, too risky to change as something could break? I don’t really know. I’m just thinking it’d have to be looked into.
ok, thanks for giving it a thought. I understand if that can’t be changed, kinda fundamental and could break something - but there is now the issue of this.
just another option, add meta-merge2
and users can migrate as needed
accretion, not breakage
@alexmiller Yeah, definitely not a fan of using the same name for breaking things. I’m onboard with that concept. I’m not sure how the separate projects are kept in sync or whatever though - meta-merge vs lein.
I think it was already mentioned to copy/rename
> If this would be fixed in Leiningen, the change would be mirrored to the meta-merge library I’m using (https://github.com/weavejester/meta-merge). Another option is to make a friendly copy and name it somethin like ctrl-merge
.
So that’s probably the meta-merge2
concept.
If Leiningen doesn't need the nil
thing, them the version 2 should be issue of the meta-merge
library, right?
If there should be a bug in the merge, effecting both meta-merge1 & 2, should the fix be applied in both? Any guidelines when to stop maintaining old versions (like soon: spec1)?
also, if a libraryX updates from using mm1 to mm2, should that lib also change the namespaces so that "no-one breaks"?
would be nice to have some written guidelines for preferred clojure accretion with libs, ping @alexmiller
There are not always simple answers to all of these questions. Rich’s Spec-ulation talk is still the best rendering of the problems
In general, turn breakage into accretion
Fixation should generally be considered non-breaking as a matter of definition
But sometimes that is subtle if users rely on the “broken” behavior