Would be easier to have an example of what you are actually trying to do? CLJS doesn’t have vars at runtime so creating one doesn’t really give you anything.
Why do you want to create a variable named by a string?
But even that, it only works if you have your string you want to create a Var from at compile time. If you wanted to say have the user type in a string at run-time and create a var from it. I’m not sure you can do that with ClojureScript macros.
Self hosted ClojureScript bundles the compiler with it, so you can’t reify Vars, but you can recompile the code itself and reload it.
At least that’s my understanding.
Vars in ClojureScript are just JS Vars, and I think namespaces are some kind of Goog.Closure nested JS object set.
The funny thing is, you can use set! it seems, and it’ll create a JS var that resolves, but it’ll keep warning that it is undeclared, since I’m guessing it doesn’t get added to some map of bindings.
> (set! foo 10)
WARNING: Use of undeclared Var cljs.user/foo at line 1
> foo
10
That doesn’t help either since set! also takes in a Symbol and is a special form so you can’t evaluate its args.
You can define the component at runtime without a macro just fine. It all depends on how you are actually planning to use the component which you have not described yet.
I will try to describe a bit further what I want to achieve then.
I am building a React library of components generated from a json file. This file is parsed by clojurescript functions in order to create the react components, for that I use reagent. My project is based on shadow-cljs.
So the workflow is the following:
; source.json
{
"HelloButton": "Click me!"
}
Which gets parsed by my cljs project and should generate a HelloButton react component into a dist.js file that can be imported in react.
So for example, if one wants to use this component, she could do the following:
I’m confused by the import {SimpleButton} from 'dist.js'; part since shadow-cljs does not support generating a file that would allow this?
Also why are you generating reagent components when they are getting used from JS?
In general when doing stuff like this it is almost always easier to just generate the source-code directly from the .json data. So don’t go with a macro, just generate .js or .cljs files separately in a simple script and just compile them regularly. Much easier to debug too.
Yes, this would be the ideal way. Currently, I am just doing a basic js import in the HTML and use the components name in the react file.
Why using reagent? well because I can leverage other tools like stylefy and I may be able to use the generated components directly in cljs at some point.
Maybe you are right; still, it seemed fairly easy to have my cljs parser working on a json file and staying in a workflow I feel comfortable and efficient. Plus it was just this one thing missing.
This is a limitation of non self-hosted ClojureScript. You can’t reify vars, and your macros cannot run at run-time.
This means only if you have access to the json file at compile time, when you convert the ClojureScript to JS, can you do it. But that’s not really allowing you to create components very dynamically, like say from a database at run-time or from user input at run-time.
Typed on my phone, but this should give you the gist.
This macro will run in Clojure, prior to compilation into JS, at that time, it will load the json, parse it, and generate a def for each components defined in it, and then the returned defs will get compiled by ClojureScript into JS.