This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-09
Channels
- # adventofcode (95)
- # announcements (22)
- # aws (2)
- # babashka (14)
- # beginners (133)
- # bristol-clojurians (2)
- # calva (43)
- # cider (11)
- # clj-kondo (82)
- # cljsrn (20)
- # clojure (100)
- # clojure-europe (12)
- # clojure-italy (9)
- # clojure-nl (7)
- # clojure-poland (1)
- # clojure-spec (4)
- # clojure-uk (105)
- # clojurescript (42)
- # cryogen (1)
- # cursive (6)
- # data-science (1)
- # datomic (5)
- # euroclojure (2)
- # figwheel (4)
- # fulcro (4)
- # garden (1)
- # graphql (3)
- # hoplon (4)
- # jobs (1)
- # joker (3)
- # luminus (4)
- # malli (15)
- # off-topic (129)
- # pathom (10)
- # re-frame (43)
- # reagent (7)
- # reitit (3)
- # shadow-cljs (31)
- # vim (6)
- # yada (39)
Are ClojureScript macros typically defined using cljs.core/defmacro
? Can they also be defined using clojure.core/defmacro
?
What I’m driving at here is to be able to distinguish macros targeting CLJS from ones targeting CLJ. Is it a fair assumption that macros defined using clojure.core/defmacro
target CLJ and macros defined using cljs.core/defmacro
target CLJS?
no, ClojureScript macros are typically defined in Clojure and use clojure.core/defmacro
e.g. you’ll have a .cljs
file with your cljs code and a .clj
file with macros that are included in your CLJS via (:require-macros)
in the ns
the only time cljs.core/defmacro
is really used is when using the self-hosted compiler. otherwise it’ll pop up in .cljc
files but typically represents a no-op
Do you mean if it's meant to be used in selfhosted cljs?
Here’s the context: https://github.com/cursive-ide/cursive/issues/1645
The issue is that in a CLJC file, when users try to get the doc in Cursive, it doesn’t show any. This is because Cursive resolves the symbol and it resolves to two places. In the case of first, it resolves to clojure.core/first
and cljs.core/first
. It’s not ideal behaviour, but Cursive doesn’t show the doc there because it doesn’t know which of the two to use.
My first attempt was to say that if one of the symbols resolved to something in a CLJ file, and the other resolved to something in a CLJS file, then show the doc from both. But that then still doesn’t work for macros - defrecord
resolves to a definition in a CLJ file and another definition in a CLJC file, which defines a macro using both clojure.core/defrecord
and cljs.core/defrecord
.
It starts getting really complicated when you have something defined in a CLJC file which uses reader conditionals to define the same thing in two different ways. Then you get a different definitions in CLJ and CLJS, but they both come from the same CLJC file.
I was just trying to understand the semantics of CLJS macros better, which I probably investigated in depth a while ago, but have since forgotten since I don’t use them much (or at all).
Other tricky cases are things like +
, which resolves to a function in CLJ but a macro in CLJS, unless it’s not in head position in which case both are functions. Cursive resolves that case accurately, but I have to take it into account for this.
My question above was really: can I tell if a macro is intended to expand to CLJS rather than CLJ? That would help me disambiguate these cases. But having thought about it, I don’t think it’s possible.
Yeah I think there's no way to differentiate here :(
Unless you could deduct this from usage of macro
If it's used in clj or in cljs files
@U0567Q30W macros can determine whether they should produce CLJ or CLJS code by checking &env
. for you from the outside they are just regular CLJ macros with no difference really.
what might provide a hint is the namespace it is declared in and whether that namespace has a :require-macros
in the ns
.
when checking x/thing
you can check if either some.thing
had a :require-macros
for itself or whether foo.bar
did something with :require-macros
or :include-macros
I wrote this not too long ago. dunno if that helps https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
but in short you can't tell by the macro definition itself only by the context it is used in
@U05224H0W Thanks, I knew the background but the gotchas are very interesting.
Hi! I’m coming from a TypeScript/ES6 background. There is this way of assembling objects in JS without mutation using spread operators that is burned onto my prefrontal cortex and I lack the experience in Clojure to find alternative ways of doing this other than assoc
constructs. Here’s what I would usually do in TS/ES6:
const obj = { a: 1, b: { c: 2} };
const newObj = { ...obj, b: { c: 3 } }; // => { a: 1, b: {c: 3} }
Here’s how I would do this in clojure:
(def obj { :a 1 :b { :c 2 })
(def new-obj (assoc obj :b { :c 3 }) ; => { :a 1 :b { :c 3}}
This is fine as long as I don’t have to deal with deeply nested maps but as soon as I’m trying to change a value nested three levels down, things start to get hairy and I’m constructing nested assoc
calls. Is there some more elegant way of doing this with deeper nested maps?
@gerome.bochmann as JS dev this might be helpful for you https://kanaka.github.io/clojurescript/web/synonym.html Though could be outdated with respect to ES6, but still useful I think
hey there o/
has anyone managed to interop with https://github.com/DevExpress/testcafe?
I haven't done testcafe, but have done https://taiko.gauge.org/ in https://github.com/filipesilva/create-cljs-app/blob/master/template/src/e2e/core.cljs#L20-L34
testcafe seems to rely on some globally defined functions like test
yeah, I found the source here: https://github.com/DevExpress/testcafe/blob/4affbb2df10b3aaacf46b834d25bbd3108fe58e0/ts-defs/index.d.ts#L1340 Right now im very unsure how to interop with this.
Im gonna have a look at Takio 🙂. I have to read up on the differences though
not too sure myself... I imagine those are being provided into window or something? maybe referencing js/window.test
works
What is the generally recommended approach for writing ClojureScript code that calls into asynchronous JavaScript code? I was debating between the approaches of Promesa [1] and cljs-promises [2]. I’m essentially attempting to translate some conventional async
/`await` JS code into CLJS and was hoping to find the most idiomatic way to tackle it.
[1] https://github.com/funcool/promesa
[2] https://github.com/AlexeyPopov/cljs-promises