Fork me on GitHub
#clojurescript
<
2023-11-13
>
stagmoose06:11:38

is there a way to force evaluate a macro parameter before doing macroexpand? i want to do (j/lit (mapv inc [1 2 3])) but the j/lit is a macro (https://github.com/applied-science/js-interop) (macroexpand '(j/lit (mapv inc [1 2 3]))) (mapv inc [1 2 3]) this will only get the cljs regular vector. how do i fix this issues (i know i can use clj->js to convert, just wonder what people normally do when they want to evaluate a thing before sending to a macro) thanks!

Martín Varela07:11:53

A big part of a macro being a macro is that it doesn't evaluate its arguments...

🙏 1
phronmophobic07:11:26

(i know i can use clj->js to convert, just wonder what people normally do when they want to evaluate a thing before sending to a macro)Generally speaking, you don't want to evaluate forms before sending them to a macro. In many cases, you can just have your macro work the with form, eg:

(defmacro my-macro [form]
  `(let [val# ~form]
     (do-something val#)))
There are a few cases where you want to do some extra work at runtime, but it depends on the use case and it's hard to give general advice without knowing more about why you might be interested in evaluating arguments to a macro.

👍 1
stagmoose07:11:00

@U060QKK2P8V @U7RJTCH6J thanks for all all your replies! this is my use case: let's say i have a js obj, which has an "js array" in obj.a.aa, (i construct it by (j/lit {:a {:aa [1 2 3 4]}}) in this example)

(j/update-in! (j/lit {:a {:aa [1 2 3 4]}}) [:a :aa] (fn [x] (clj->js (mapv inc x))))
the above code achieve what i want, however this doesn't:
(j/update-in! (j/lit {:a {:aa [1 2 3 4]}}) [:a :aa] (fn [x] (j/lit (mapv inc x))))
because j/lit is a macro

Martín Varela07:11:49

What does j/lit do?

Martín Varela07:11:02

and does it need to be a macro, in the first place?

Martín Varela07:11:20

As a general rule, avoid using macros as much as you can

🙏 1
stagmoose07:11:42

j/lit returns literal js objects/arrays for an arbitrarily nested structure of maps/vectors from https://github.com/applied-science/js-interop

stagmoose07:11:02

i was thinking replace clj->js with j/lit

phronmophobic07:11:07

It looks like j/lit is for literals and mapv inc x) is not a literal

👆 1
🙏 1
stagmoose07:11:56

i guess j/lit will be more performant than clj->js (i am not sure yet haha)

phronmophobic07:11:56

If the work can be done at runtime compile time (see correction below), then j/lit can help, but if the value is only available at runtime, then a macro has little benefit.

🙏 1
stagmoose07:11:48

"If the work can be done at runtime" do you mean compile time

stagmoose07:11:30

gocha, thanks for your help! looks like i will stick to clj->js for now~

👍 2
martinklepsch13:11:41

Hey! I'm trying to write a macro for instrumentation purposes, it's similar to with-open in Clojure but I'm not quite getting it right... 🧵

martinklepsch13:11:25

(defmacro with-span
      "Wrap the body in a tracing span identified by `ident`.
      If body returns a promise, this will return a promise as well."
      [[ident opts] & body]
      `(do
        (start-span* ~ident ~opts)
        (let [result# (do ~@body)]
          (if (p/promise? result#)
            (p/then result#
                    (fn [x#]
                      (finish-span* ~ident {})
                      x#))
            (do (finish-span* ~ident {})
                result#)))))
This is my current version and I can call it from Clojurescript but there's some issues: 1. When calling (with-span [:foo :bar] (p/delay 1000)) it looks like ident, opts and body are all nil 2. Calling the macro in a REPL does not actually evaluate the code but returns it as a quoted list (it seems), maybe this is normal? :thinking_face:

martinklepsch13:11:20

I tried getting some help by ChatGPT, which seemed helpful at first but ultimately told me to come here: > If you continue to experience issues, it might be helpful to create a minimal reproducible example that isolates the problem, which you can use to seek further assistance from the ClojureScript community or on forums like ClojureVerse or the Clojurians Slack. 😅

thheller14:11:30

remember that macros are in CLJ, not CLJS

thheller14:11:51

can't tell if you did that part correctly from the code

martinklepsch16:11:55

I was trying to use that blogpost as a guide, after moving the macro into a separate .clj file it seems to work as expected 🙂 thank you for writing it!

souenzzo13:11:36

why is https://github.com/clojure/clojurescript/blob/v1.11/src/main/cljs/cljs/core.cljs#L1332 experimental? What does it means? It can be removed? change?!

Roman Liutikov14:11:54

I guess it means it was added quickly and never revisited since then.

Roman Liutikov14:11:18

Nevertheless it works well

souenzzo14:11:30

Maybe related ticket: • https://clojure.atlassian.net/browse/CLJS-2527 Just log here. I'm preparing to raise it to #C07UQ678E

dnolen16:11:26

@souenzzo at the time it was added it was unclear how useful it would be (and it was specific to ClojureScript), ES6 adoption wasn’t so pervasisve - we can probably remove the EXPERIMENTAL bit now that so much time has passed

p-himik17:11:14

FWIW, I'd prefer for the ES6 functions to stay. Some JS APIs use the ES6 iterators (e.g. URLSearchParams.entries), GCL uses them at least in goog.iter.

👍 1
dnolen17:11:42

sorry I meant remove the “EXPERIMENTAl” part - actually removing a fn - no way 🙂

souenzzo09:11:06

(I had to use exactly because of URLSearchParams.entries)

Noyal Jose17:11:29

hi, I am learning Clojurescript and i'm new to js. So I have no idea what properties like .-onkeyup, .-keyholder means, along with other js based functions such as .getElementById where can i learn all of this from. Can you point me to some resources?

p-himik17:11:23

Those properties are from JS, not CLJS. I'd suggest looking them up on the MDN website. The keyholder property doesn't sound familiar at all though, so perhaps it comes from some JS library.