This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-22
Channels
- # 100-days-of-code (3)
- # announcements (7)
- # beginners (147)
- # cider (22)
- # cljdoc (24)
- # cljs-dev (71)
- # cljsrn (8)
- # clojars (3)
- # clojure (45)
- # clojure-conj (11)
- # clojure-dev (1)
- # clojure-italy (21)
- # clojure-nl (2)
- # clojure-spec (76)
- # clojure-sweden (2)
- # clojure-uk (100)
- # clojurebridge (3)
- # clojurescript (15)
- # cursive (7)
- # data-science (2)
- # datomic (7)
- # emacs (9)
- # events (2)
- # figwheel-main (4)
- # fulcro (117)
- # jobs (2)
- # jobs-discuss (21)
- # leiningen (184)
- # nyc (4)
- # off-topic (50)
- # planck (6)
- # re-frame (14)
- # reagent (25)
- # ring-swagger (5)
- # shadow-cljs (96)
- # spacemacs (5)
- # sql (26)
- # tools-deps (12)
- # uncomplicate (1)
- # yada (3)
For anyone familiar with the CLJS implementation of clojure.spec, do you have any insight into the difficulty of fixing this bug? https://dev.clojure.org/jira/browse/CLJS-2940
I bet CLJS-2940 can be further constrained to things involving s/nilable
(in other words, I think the ticket title incorrectly implies a broader problem than that exhibited in the description). I’ll update it.
I'm not sure about explicit documentation but there is s/*recursion-limit*
so they are meant to be supported
I’m going off on a tangent that is better suited for #clojure-spec channel now though, so nvm here.
I wonder if we could update cljs.core/merge-with
to match clojure.core/merge-with
, now that maps produce map entries. (Specifically changing first
to key
and second
to val
in the implementation.)
I think the previous change already forced people to stop relying on the old semantics
I’ll put together a ticket for it, with perf numbers. Then we can let it sit for a while for consideration / soaking.
Hah, here is an example of code this patch would break, which doesn't rely on the older use of 2-vectors as ersatz map entries, but simply on the fact that of first
/ second
are being used in the merge-with
implementation
(->> [:a 1 :b 2] (partition 2) (merge-with vector {}))
In the wild here https://github.com/gf3/secretary/blob/1f2036a694e49f58a97c9401878602148f9d6310/src/secretary/core.cljs#L252
TIL there is a name for this concept: Hyrum's Law http://www.hyrumslaw.comeww (re using sequences and first/second for entries)
I guess, since Clojure and ClojureScript are "popular", Hyrum's Law states that someone will have discovered that first
and second
are hiding inside merge-with
map entries should always be indexed / positional
Hyrum's Law also seems to imply you can't change anything in core without breaking someone.
This merge-with
use also seems to rely on an undocumented aspect of conj
that happens to work (I can't recall why, but it feels like it is an accidental internal implementation detail):
(conj {:c 3} (seq {:a 1, :b 2}))
not accidental
conj on maps expects something that seqs to map entries (which can be maps, but can also be just seqs of map entries)
keys
and vals
have the same relaxed expectation
user=> (keys (seq {:a 1, :b 2}))
(:a :b)
I am increasingly running into cases where it would be useful to be able to state that something “seqs to map entries” (often in spec-related stuff)
Rich and I have talked about it a couple times, maybe that will emerge as an abstraction at some point, dunno
Sounds like some of the subtleties you have run across while spec'ing core, I guess?
yep, although I think I ran into it in the spec implementation, not in a spec
I applied shadow-cljs to myu project and it seems to work just fine, except for hot reload. It does watch my changes and recompiles but in my browser the changes are not visible and refresh also doesn't bring changes.
“seqs to map entries” is weaker than map?
but still sufficiently interesting to be useful
If those use cases you mention are by design, then "seq to map entries" definitely sounds like it could use a name in spec.
@dnolen Yeah, for that particular case I'll probably file a ticket against the downstream repo.
@andy.fingerhut the problem is that there is no easy way to write that predicate
without actually forcing the seq
Do you consider it a requirement, or just a really really good idea, for a spec not to force a seq?
I gotta say, this is totally badass. I never knew:
(keys (filter (comp pos? val) {:a 0, :b 1}))
more interestingly, the example from secretary uses this:
(->> [:a 1 :a 2 :b 3] (partition 2) (merge-with vector {})) ;;=> {:a [1 2], :b 3}
, so you cannot simply replace (partition 2)
with (apply hash-map)
to fix it. But converting the 2-colls to map-entries will make it work with the patch.
> conj on maps expects something that seqs to map entries (which can be maps, but can also be just seqs of map entries)
Perhaps instead of "seqs to map entries" it is "is a seq of map entries"?
(Compare (conj {:c 3} (vec (seq {:a 1, :b 2})))
and (conj {:c 3} (seq (vec (seq {:a 1, :b 2}))))
)
but yeah, the "problem" here is that vectors take the path of a map entry, rather than that of a collection of map entries
the spec according to the impl would be: conj on maps takes either a map entry or a vector of size 2 representing a map entry, or something that seqs to map entries which is not a vector
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java#L25-L45
Regardless of spec, an interesting question is whether the docstring for conj
should essentially say what you just said. 🙂
Maybe even: "conj on maps takes either a map, a map entry or a vector of size 2 representing a map entry, or something that seqs to map entries which is not a vector"
>> conj expects another (possibly single entry) map as the item, and returns a new map which is the old map plus the entries from the new, which may overwrite entries of the old. conj also accepts a MapEntry or a vector of two items (key and value)
this is what http://clojure.org says
and I suspect that the implementation accepts it just because that was the easiest way to implement map+map merging
That's what I thought. It was an internal accident of implementation based on ease of implementation. But Alex's comment is that it is instead intended to be supported, not as an accident.