Fork me on GitHub
#clojurescript
<
2022-10-04
>
Niclas19:10:46

Does anybody know how one can work with namespaces in ClojureScript? Kinda fuzzy question, I know, but why aren’t there fns like (all-ns), (ns-interns) etc in CLJS when they’re present in CLJ? I’m toying around with some meta-ish programming and looking for alternatives to ns discovery.

p-himik19:10:41

And https://clojurescript.org/about/differences#_vars_and_the_global_environment. Specifically the "intern not implemented - no reified Vars" part.

Niclas19:10:42

I’m by no means a compiler designer, but feels to me like it should be possible to hold a global registry of all defined ns/vars/etc that’s available at runtime?

phronmophobic19:10:26

it's totally possible, but optimizing the size of the javascript output is usually much more important than the value from having the global var registry available at runtime

p-himik19:10:36

Nope, not at run time. Some things are available at compile time though. E.g. ns-interns is a macro in CLJS, so you can use it, but with a statically provided symbol.

phronmophobic19:10:21

depending on your use case, you can work around it by keeping your own registry, using something like https://github.com/babashka/sci, or using self hosted clojurescript

Niclas19:10:22

Mega bummer 😢

p-himik19:10:32

Yeah, due to optimizations, something like my.project.core/some-var might end up being just Vx in a scope of some function.

Niclas19:10:50

I think this is pretty neat, but that makes it impossible to do in cljs then https://github.com/Looveh/clj-meta-spec

p-himik19:10:26

Actually, that should be possible, assuming all information is there at the compile time.

phronmophobic19:10:42

this looks like a linter? it seems like you could do that with clj-kondo

p-himik19:10:03

It's not a linger, it's a semi-automatic spec'er.

👌 1
p-himik19:10:22

Just a convenience over s/fdef.

phronmophobic19:10:17

ah, I think you should still be able to do that as a macro. Vars and var metadata is generally available at compile time.

timothypratley19:10:36

Right, you certainly can. If you want to use it as is you could just write most of your code in CLJC, then you can run the tool in Clojure. I tend to take this approach because running tests is more convenient in Clojure. ¯\(ツ)

Niclas19:10:33

Ah interesting!

Niclas19:10:38

How can I find the namespaces and ns-interns during compile time if (all-ns) etc aren’t available?

timothypratley19:10:00

ns-interns etc are all available at compile time, it's kind of confusing... but whenever you define a macro, you are writing CLJ code that will run at compile time. So for example you could write a macro that does those things

p-himik19:10:11

And all-ns in CLJS is actually cljs.analyzer.api/all-ns, and it's slightly different.

Niclas19:10:59

Ah awesome, thanks!

Niclas19:10:15

I’m sure there’s all good reasons for these diffs between clj and cljs and I’m glad both dialects exist, but I really find these diffs confusing

1
clojure-spin 1
cjohansen21:10:39

Is it possible to create macro that does (defn ^:export n [] ,,,) ?

p-himik21:10:08

Yes. You can use with-meta.

cjohansen21:10:45

Yes, I tried like so:

(defmacro defexport [binding & body]
  `(def ~binding (with-meta
                   (fn [args#]
                     ,,,)
                   {:export true})))

cjohansen21:10:59

Didn’t seem to export anyway?

p-himik21:10:29

But... that's a def, not a defn. And the meta is on the function and not on the symbol.

cjohansen21:10:14

Aha, of course

cjohansen21:10:26

The meta goes on the var, not the function

cjohansen21:10:52

Actually, I’m still not sure where to place the with-meta :thinking_face:

cjohansen21:10:08

(defmacro defexport [binding]
  `(defn ~(with-meta binding {:export true}) []
     true))

cjohansen21:10:12

Thanks! 🙂

👍 1