Fork me on GitHub
#clojurescript
<
2024-05-21
>
Ernesto Garcia08:05:27

Hi all. I'm trying to create a macro that relies on another macro. However, that another macro uses a backquote to resolve symbols from CLJS namespaces, and therefore my client macro won't compile. Is there a solution for this?

Ernesto Garcia08:05:43

Some code:

(ns project.web.util.svg-icons
  (:require [hickory.core :as hickory]
            [reagent-mui.util :refer [create-svg-icon]]))

(defmacro resource-as-hiccup [resource-name]
  (-> ( resource-name) slurp hickory/parse-fragment first hickory/as-hiccup))

(defmacro make-svg-icon [icon-name resource-name]
  (create-svg-icon
    `(r/as-element ~(resource-as-hiccup (str "project/web/icons/" resource-name)))
    icon-name))
create-svg-icon can be found https://github.com/arttuka/reagent-material-ui/blob/4fc4b44891919d2b84160eb411d52227dd89e0a5/src/core/reagent_mui/util.clj#L31. It has a react/memo call inside a backquote. I get the error: "No such namespace: react"

p-himik08:05:44

You have to explicitly require react in the CLJS namespace that uses that macro.

Ernesto Garcia08:05:01

I do that. But the macro doesn't even compile. react is being resolved when compiling the make-svg-icon macro. Of course it doesn't exist there, as that is a Clojure context.

thheller10:05:50

looks to me like defmacro resource-as-hiccup should be defn resource-as-hiccup? as in just a function you call, or in case the CLJS code actually does use it as a macro someplace you turn it into a function that the macro then calls

thheller10:05:05

(defn resource-as-hiccup* [resource-name]
  (-> ( resource-name) slurp hickory/parse-fragment first hickory/as-hiccup))

(defmacro resource-as-hiccup [resource-name]
  (resource-as-hiccup* resource-name))

(defmacro make-svg-icon [icon-name resource-name]
  (create-svg-icon
    `(r/as-element ~(resource-as-hiccup* (str "project/web/icons/" resource-name)))
    icon-name))

thheller10:05:07

something like that

thheller10:05:10

beware the macro hell though. you are digging quite deep with that many macros, some of those likely should just be functions.

Ernesto Garcia10:05:11

You're right. In this case I think I will need to call create-svg-icon as if it where a function, so that it is not compiled in place at the Clojure level. But the problem is that that macro is in a library...

thheller10:05:04

just saw that the quote was misplaced. should likely be something like

(defmacro make-svg-icon [icon-name resource-name]
  `(create-svg-icon
     (reagent.core/as-element ~(resource-as-hiccup* (str "project/web/icons/" resource-name)))
     ~icon-name))

Ernesto Garcia11:05:33

Of course, that works! Thank you!

Ernesto Garcia11:05:00

Macros are expanded recursively