This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-17
Channels
- # announcements (1)
- # babashka (21)
- # beginners (46)
- # calva (21)
- # cherry (10)
- # cider (5)
- # clojure (54)
- # clojure-europe (16)
- # clojure-nl (2)
- # clojure-norway (37)
- # clojure-spec (7)
- # clojure-uk (4)
- # clojurescript (30)
- # conjure (3)
- # cursive (1)
- # datalog (5)
- # datascript (3)
- # datomic (13)
- # emacs (5)
- # fulcro (82)
- # girouette (1)
- # helix (4)
- # hyperfiddle (2)
- # joyride (1)
- # juxt (1)
- # kaocha (4)
- # lambdaisland (3)
- # luminus (1)
- # malli (15)
- # off-topic (60)
- # pathom (3)
- # polylith (1)
- # practicalli (3)
- # releases (1)
- # ring (4)
- # sql (3)
- # squint (85)
A question related to the performance of using a constant map inside a function. Imagine I have a code like this:
(defn foo [x]
(let [a {:a 1}]
(get a x)))
In JVM Clojure, the map {:a 1}
is a static member of the class that represents foo
. Therefore the map is not created on each function call. While in ClojureScript (at least according to Klipse), the map is created on each function call, like this:
cljs.user.foo = (function cljs$user$foo(x){
var a = new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword(null,"a","a",(-2123407586)),(1)], null);
return cljs.core.get.call(null,a,x);
});
Here is the Klipse http://app.klipse.tech/?cljs_in=(defn%20foo%20%5Bx%5D%20(let%20%5Ba%20%7B%3Aa%201%7D%20b%20%7B%3Ab%20x%7D%5D%20%5Ba%20b%5D)).
Is there a performance improvement opportunity here or are the common JS engine smart enough to optimize the code automagically?In the meantime, if you have a real need, wouldn't this mildly messy looking closure capture the initial map for you?
(def foo
((fn []
(let [a {:a 1}]
(fn [x]
(get a x))))))
(foo :a) ;; => 1
But then the code is unreadable!
Top level fn defined not at the top level vs anonymous fn inside a self-invoking function. Conceptually, the top level let somehow feels more gross to me. But it is definitely easier to read and understand, and requires building fewer objects. I guess pick your 🤢 poison. Either way, you could always hide the ugly behind a macro.
something similar is already done for keywords, historically Closure had issues removing top level constructions if they were a bit complex so we didn’t bother
You meant Clojure. Right? What is already done with keywords?
is it safe to use set! in :advanced compiled cljs in the way that one would use intern in clojure, to redefine vars from other namespaces? if not is there a workaround?
Hi all, I have 2 .CLJC
files one is for view, the other one is for common stuff (macros etc.);
(ns panel.common)
(defmacro print-me-in-cljs []
`~(read-string {:read-cond :preserve} "#?(:cljs (println \"Hey!\"))"))
Also, I tried this one as well;
(defmacro print-me-in-cljs []
`~(reader-conditional '(:cljs (println "Hey!")) false))
-
(ns panel.views
(:require-macros
[panel.common :as common]))
(common/print-me-in-cljs)
The problem is that when I open the web page, I can not see the "Hey" output inside the browser's console.
I'm trying to create a macro that expands readers conditionals so in .CLJC
files (view ns) I don't have to define #?(:cljs ... :clj ...)
(macro handles it for me)I think that might be impossible because reader conditionals happen BEFORE macroexpansion but not sure
If that's the case, it's very sad 😞
reader conditionals happen in the reader, which is before macroexpansion
it's probably possible to do what you are trying to accomplish, but not the way you're trying to accomplish it, but I would test the order of these things because intuitively/vague memory it can't be done
Thank you! @U064X3EF3 and @U63D7UXJB
if you want something to happen in clojurescript but not clojure, it can definitely be done and probably quite flexibly but the reader way isn't good, instead can you use the reader or something else to create a runtime variable to know which environment you're running in and dispatch based on that?
I think if you search here, you'll find this is a common question (I'm not an expert in this area to tell you what it is)
@U63D7UXJB Yes, I need something like this - I'll think about it, thanks for the tip!
I think also, what you actually want is conditional writing (the macro emits code that varies depending on its runtime environment)
not clear to me what you're really trying to do but that would work for some things at runtime? (def env #?(:cljs :cljs :clj :clj)) then use that? could also work at macro-expansion time I think, but the information might already bein the &env parameter that gets passed to all macros (?) https://clojure.org/reference/macros
> I think also, what you actually want is conditional writing (the macro emits code that varies depending on its runtime environment) (edited) Yes, I need this I guess
> not clear to me what you're really trying to do but that would work for some things at runtime?... Let me check this
@U63D7UXJB this did the trick!
(defmacro print-me-in-cljs []
`(if '~(:js-globals &env)
(println "ClojureScript")
(println "Clojure")))
Nice! Not sure whether the long term goal is advised for your health but the sooner it's implemented the sooner the damage can be calculated xD
I went hunting for something similar and found some prismatic code here https://github.com/plumatic/schema/blob/master/src/clj/schema/macros.clj#L13-20 though in the end it turned out I didn’t actually need it so never tried…
FWIW here's something that might interest you: https://github.com/cgrand/macrovich (and it uses the (:ns &env)
trick as well).