This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-26
Channels
- # announcements (4)
- # beginners (160)
- # boot (2)
- # calva (40)
- # cider (41)
- # clara (24)
- # cljdoc (2)
- # cljs-dev (99)
- # clojars (4)
- # clojure (71)
- # clojure-dev (9)
- # clojure-europe (4)
- # clojure-italy (2)
- # clojure-nl (19)
- # clojure-spec (97)
- # clojure-uk (103)
- # clojurescript (57)
- # core-logic (1)
- # cursive (15)
- # data-science (31)
- # datomic (24)
- # duct (1)
- # emacs (39)
- # events (7)
- # figwheel-main (14)
- # fulcro (44)
- # garden (7)
- # jobs (13)
- # juxt (1)
- # leiningen (29)
- # music (2)
- # nyc (4)
- # off-topic (37)
- # pathom (12)
- # re-frame (26)
- # ring (1)
- # ring-swagger (10)
- # shadow-cljs (35)
- # spacemacs (2)
- # specter (4)
- # test-check (67)
is it true that (:require [foo.bar :include-macros true])
causes the :include-macros true
clause to effectively be implicitly present for requires of foo.bar
in every other namespace?
yes, kinda accidentally. https://dev.clojure.org/jira/browse/CLJS-2454
I was hoping to rely on the opposite
Is the whole implicit sugar thing just a variant of this?
it doesn't matter how the macro namespace is loaded. once it is loaded it will always be used.
maybe the question is: you should not rely on CLJS-2454, but isn’t the implicit sugar thing exactly this?
not really. the :require-macros
sugar ensures that the macros will be loaded and accessed properly
without you are relying one something doing :include-macros true
somewhere at least once in your build
yes, but in a different place. it is added to the consumer ns, not the provider ns .. for the lack of better words ...
I see, so there is a different mechanism in self-requiring in the provider ns, or requiring the macros from a consumer ns?
(ns foo.consumer
(:require [foo.thing :include-macros true]))
(ns foo.consumer
(:require-macros [foo.thing])
(:require [foo.thing]))
with the "self-require" the consumer does not need any knowledge of whether there are macros or not
(ns foo.consumer
(:require [foo.thing]))
(ns foo.thing
(:require-macros [foo.thing]))
Understood yeah. But if a consumer ns1 would have used require-macros [foo.thing], could consumer ns2 get away with not doing that and still use the macros from foo.thing without a self-require? It seems to be that it’s the same mechanism (getting the analyzer in the right state), so I don’t get why you should not rely on it in CLJS-2454.
> it doesn't matter how the macro namespace is loaded. once it is loaded it will always be used.
yes, but “you should not rely on it”, that’s the part what I’m asking about effectively 🙂
you should not rely on it unless you can guarantee that the ns with the "side-effect" of loading the macros will ALWAYS be loaded first
tl;dr: requiring macros in CLJS is side-effecting (once a var is identified as a macro, it stays a macro), so you should not rely on the order of loading namespaces. better is to do a self-require, then the side effect happens predictably and at the right time. is that a good summary?
A question related to key
and val
. In Cljs 1.9, it used to work when we called key
or val
on a 2 element sequence. Now in Cljs 1.10 it breaks. I know that calling key
or val
on a seq is not accurate but it used to be tolerated. What’s the rationale of this breaking change?
I don't know anything about cljs, but I'd say that is fixing something broken
did this maybe change when MapEntry was introduced as a proper type in CLJS? Before that 2-element vectors were used.
Most recently merge-with
was also brought up to date using MapEntry
which broke secretary, the client side routing lib
(key ['a']) definitely would have worked, and that stopped working because of MapEntry
Here’s the patch for merge-with, showing some perf benefits: https://dev.clojure.org/jira/browse/CLJS-2943
In the app of my customer, there are hundreds of occurences of key, val and vals
I am very tempted to add an implementation of IMapEntry for all the sequences. Something like:
(extend-protocol IMapEntry
PersistentVector
(-key [v] (first v))
(-val [v] (second v)))
It feels like a dangerous hack
Any thoughts?
could work as an intermediate solution to an upgrade. emit a warning in those implementations and fix them one by one?
as far as I can see and remember, only PersistentVector implemented IMapEntry until https://github.com/clojure/clojurescript/commit/620ac16d93a91786e1c636fac1269ed66087aa03/src/main/cljs/cljs/core.clj
https://github.com/clojure/clojurescript/commit/620ac16d93a91786e1c636fac1269ed66087aa03 ?
the idea with key and val is that they are "slots" in a tuple, directly accessible via a lookup (not a traversal)
MapEntry is a custom 2-tuple for it
vectors are plausible (as slots with direct access)
seqs are right out and you should feel bad if you did that :)
My customer did that and he really feels bad
I would say there are mixed feelings around "vectors of exactly length 2" being map entries. kind of a kludge but also awfully useful. Ideally we'd have actual fixed length tuples and use a 2-tuple. Maybe someday.
@alexmiller I think the issue here is he is upgrading clojurescript, and clojurescript used to impl key and value on PV, but now doesn't because it introduced MapEntry
yeah, I get it
clojure has shifted a bit on this too
becuase he was accidentally using key and val on PV that were not of map-like provenance
we went down the tuple path for a bit in 1.7(?) and I think there were some alpha/betas where that worked
(in both Clojure and ClojureScript) - I guess that’s also convenience, expecting people to manually create MapEntries is also not very nice. On the other hand, you can use assoc
.
and the previous behavior wasn't something that people were consistently relying on - and the number of complaints hasn't been that significant