This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-07
Channels
- # beginners (73)
- # boot (20)
- # chestnut (8)
- # cider (36)
- # clara (37)
- # cljs-dev (21)
- # cljs-experience (1)
- # cljsrn (2)
- # clojure (163)
- # clojure-austin (3)
- # clojure-dusseldorf (6)
- # clojure-finland (1)
- # clojure-ireland (4)
- # clojure-italy (45)
- # clojure-russia (9)
- # clojure-spec (47)
- # clojure-uk (20)
- # clojurescript (107)
- # cursive (24)
- # data-science (4)
- # datomic (4)
- # defnpodcast (1)
- # fulcro (1)
- # heroku (3)
- # jobs-discuss (4)
- # juxt (52)
- # lein-figwheel (1)
- # leiningen (4)
- # lumo (37)
- # midje (5)
- # off-topic (16)
- # onyx (15)
- # portkey (11)
- # re-frame (112)
- # reagent (12)
- # rum (1)
- # specter (35)
- # uncomplicate (6)
There's probably no simple way to use a macro that has nodejs dependencies, huh? I'd like to have some constants calculated at compile time, but they're calculated using a couple nodejs modules.
@mfikes @dnolen Thanks. So, does `^:export prevent inlining? Or, more precisely: does it guarantee that future version of Closure will never inline the function? A quick search just now was non-conclusive. Background: This is for https://github.com/deg/re-frame-firebase, a Firebase wrapper for re-frame. Firebase has the notion of subscribing to database changes, which I wrap it in a re-frame subscription. Sometimes, I will want the Firebase subscription to remain active for the entire lifetime of a large component, even though I actually use it only in a small inner component. Re-frame handles this nicely, guaranteeing that each subscription is only created once. So, I just need to create the subscription in the outer component and all behaves as expected. But, of course, it's not enough to just create it; it must be used by the mounted component. Naively, I could just write out the entire contents of the database to an invisible div, but that has obvious, ummm, issues. So, I wanted to write a function that depends on the subscription, but generates minimal output. The null function is the obvious end-point of this process, and works perfectly when not optimized. But, obviously, any optimizing compiler would be 200% reasonable to inline it down to nothing.
Hello, anyone know why specifying closure-defines with optimisations set to whitespace
has no effect?
@deg ^:export
doesn't prevent inlining. It provides a stable external name for a function so that it can be called. See https://clojurescript.org/reference/advanced-compilation#access-from-javascript
(The exported name is stable, and will point to the internally renamed name, and that internal function could be inlined into other code being compiled with :advanced
that might also call it.)
No. Closure doesn't give you control over inlining. But it doesn't appear that that's what you are interested in controlling.
No. I want the optimizer of the calling function to believe that the parameter is needed, by not being able to peek into null-op
. So, either I want to prevent inlining of null-op
or some way of declaring that a local variable must be preserved even though it appears to be unused.
De facto, the current null-op
seems to do what I want, in one test case of advanced compilation. But, based on what you said, I can't rely on that.
So, either I'll just put it into a hidden :div. Or, probably better, I'll take a closer look at how re-frame or reagent decide when to keep it. Possibly, they are code-walking before optimization, so all this is moot.
@dnolen. For the sake of the lifetime of the subscription. I'm handwaving here on very thin ice because I don't actually know how re-frame is working this mojo. This one line hack worked empirically, so I asked here to see if made sense that it is working.
I would put all of these other details aside as they don’t seem relevant - my question is trying to get at the real requirement here
You may have missed a line above... See my "background", about a dozen messages up. Restating:
I should probably stop here. I have something that is working de facto, but I don't understand enough about what re-frame is doing.
Your reaction strongly suggests that I'm driving down a long pier based on a wrong assumption.
right so my understanding so far is that you believe there is an issue where none exists
What I observed is that my :on-dispose (in the code above) is called when the inner component is unmounted; if and only if the outer component "sufficiently" uses the subscription
right so you trying to explain what you’ve observed … problem is without something minimal it’s hard to say
By observation, doing a re-frame/subscribe, dereferencing it, and holding the result in a local variable is not sufficient.
My assumption now is that re-frame is doing a code walk which, now that I think about it, is obviously pre-closure. So, this all may just work.
re-frame's code walker must run before the closure optimizer. So, whatever cleverness it is doing, it can't be hurt by the optimizer.
For my own curiosity, I should now dive into the re-frame, and maybe reagent, code and stop treating them as a black boxes. But, that's my problem challenge/homework. 🙂
yeah I’ve never thought about how advanced optimization may interact with my reagent/re-frame code and I haven’t seen any real issues around it myself
Yup. I was diving down to a level that was new to me... first time using reg-sub-raw, etc. And the external connectivity to the database made me more concerned about performance; then some trace prints raised concerns and ... before you know it.... deep down the rabbit hole.
FWIW, I would love it if anyone has time to code-review https://github.com/deg/re-frame-firebase. It's at a big enough intersection of interests that it may become relatively widely used. I'm not convinced that I didn't make any mistakes that might bite other users. ... I was definitely learning as I wrote it.
I can't see why I'm getting undefined reference errors from (and js/symbol (contains? (.keys js/Object js/symbol) "key"))
I basically want to know if symbol is loaded as boolean (false/nil instead of errors)
I had diffuculty interoping the typeof function
> (.typeof js/asdf)
#object[ReferenceError ReferenceError: asdf is not defined]
nil
js/typeof or .typeof js/window did the sameThe interop call will be compiled to asdf.typeof
, which clearly shows that even if such method existed, it wouldn't work if the object is null
besides this
(core/defmacro exists?
[x]
(bool-expr
(core/list 'js* "typeof ~{} !== 'undefined'"
(vary-meta x assoc :cljs.analyzer/no-resolve true))))
🙂you can call typeof through goog/typeOf
@juhoteperi right but that won’t work for undefined global things
@hlolli it’s just how JavaScript works, and exists?
is a short cut for that pattern since we don’t support direct usage of typeof
operator
yes, I'm happy with this, bit unintuitive at first, you often see var a = a || {}; patterns in js.
It appears that it is the requirement of cljs.spec.test.alpha
that causes the inclusion of clojure.test.check.generators
in Clojurescript. In this segment https://clojure.org/guides/spec#_generators it appears to be clojure.spec.gen.alpha
-> cljs.spec.gen.alpha
that would cause clojure.test.check.generators
to be included.
found it: https://stackoverflow.com/questions/9218044/in-clojure-how-to-apply-and-to-a-list
Based on the documentation, I expected that cljs.spec.gen.alpha
would bring in clojure.test.check.generators
, but it actually seemed to be cljs.spec.test.alpha
that did so.
@samedhi I wasn’t aware that any documentation implied anything here about the ns dep graph
For sure, I was just translating what I was seeing here https://clojure.org/guides/spec#_generators
Sure thing, is this slack unlimited (that is, will my comment stay here forever) or is it on the cutoff free plan?
no it will be thrashed so that is why there is a big debate going on concerning what are the alternatives...
when using map-indexed is there a way of avoiding writing an anonymous function just to return the two params as it is? (eg I did not find a two-parameter identity fn)
Is there a way to convert an ast
back to cljs
? tools.analyzer.js
was abandoned and can't find anything in cljs.api
Is it possible to pass in :arglists to a function meta that already takes args, alter-meta! is not working and neither does this
(defn aarg
{:arglists '[whereami]}
[& {:keys [:a :b :c]
:or {:a 1 :b 2 :c 3}
:as env}]
(+ 2 2))
=> {... elided... :end-line 1,
:arglists ([& {:keys [:a :b :c], :or {:a 1, :b 2, :c 3}, :as env}]),
:doc nil, ..elided... }
is the missing ^
a typo?
cljs.user=> (defn ^{:arglists '([fake]) :other-key :OK} aarg [])
#'cljs.user/aarg
cljs.user=> (meta #'aarg)
{:other-key :OK, :ns cljs.user, :name aarg, :file nil, :end-column 49, :column 1, :line 1, :end-line 1, :arglists ([]), :doc nil, :test nil}
the other meta is there to ensure that at least that part is correct
it still fails though
I was really able to add arglists when I had no arguments in the function, then '[whereami] would show in the arglists. I have destructured args for the function I want to modify the arglists for.
(defn aarg
{:arglists '[whereami]}
[]
(+ 2 2))
=> {... :end-line 1,
:arglists (whereami),
:doc nil, ...}
wow, I wasn’t aware that a hash-map before the args vector was a thing that worked…
the doc calls it attr-map
fascinating
this appears to actually work
(ins)cljs.user=> (defn aarg {:arglists '([fake])} [a])
#'cljs.user/aarg
(ins)cljs.user=> (meta #'aarg)
{:ns cljs.user, :name aarg, :file nil, :end-column 11, :column 1, :line 1, :end-line 1, :arglists ([fake]), :doc nil, :test nil}
(ins)cljs.user=> (defn aarg {:arglists '([fake])} [[a b]])
#'cljs.user/aarg
(ins)cljs.user=> (meta #'aarg)
{:ns cljs.user, :name aarg, :file nil, :end-column 11, :column 1, :line 1, :end-line 1, :arglists ([fake]), :doc nil, :test nil}
(defn aarg {:arglists '([fake])} [& {:keys [:a :b :c] :or {:a 1 :b 2 :c 3} :as env}])
not the correct :arglists here in the metadata.could be…