shadow-cljs

2026-04-29T14:46:23.207929Z

in a cljc file, i have a macro that i'm self-requiring with (:require-macros lazytest.core), and then i'm later using in functions. when i compile the file with cljs, there's no warning, but when i compile with shadow-cljs, i see :undeclared-var warnings:

------ WARNING #6 - :undeclared-var --------------------------------------------
 File: /Users/noah/programming/lazytest/src/clojure/lazytest/core.cljc:449:30
--------------------------------------------------------------------------------
 446 |                        msg
 447 |                        {:message msg
 448 |                         :file #?(:clj *file* :cljs (.-fileName (js/Error. "")))
 449 |                         :ns (current-ns)
------------------------------------^-------------------------------------------
 Can't take value of macro lazytest.core/current-ns
in what way is this a "take value of macro"? why isn't this being executed/replaced when the file is parsed?

thheller 2026-04-29T14:50:13.871079Z

I can't say without seeing the code in context. what is current-ns? its not a core function

2026-04-29T14:55:53.103069Z

(defmacro current-ns []
  (ns-name *ns*))

;;; Utilities

(defn ^:no-doc merged-data
  "For internal use only."
  [body form docstring metadata]
  (merge {:doc docstring
          :file #?(:clj *file* :cljs (.-fileName (js/Error. "")))
          :ns (current-ns)}
         (when (empty? body) {:pending true})
         (meta form)
         {:metadata metadata}))

thheller 2026-04-29T14:56:48.080929Z

uhm that won't work. I mean it'll always be lazytest.core

thheller 2026-04-29T14:57:36.261869Z

thats as if you had written

(defn ^:no-doc merged-data
  "For internal use only."
  [body form docstring metadata]
  (merge {:doc docstring
          :file #?(:clj *file* :cljs (.-fileName (js/Error. "")))
          :ns "lazytest.core"}
    (when (empty? body) {:pending true})
    (meta form)
    {:metadata metadata}))

2026-04-29T14:58:16.907609Z

damn

thheller 2026-04-29T14:58:43.166079Z

hmm thats even true in clojure?

2026-04-29T14:59:09.319599Z

well, it was previously just *ns* so i'm trying to make something dialectical

thheller 2026-04-29T15:00:06.393389Z

if thats from a macro context use that macros &env to get (:name (:ns &env)) or *ns* captured during macro expansion. can't do it in a defn

2026-04-29T15:02:12.934149Z

so having a macro that calls (:name (:ns &env)) isn't enough if it's used in a defn context? it'll carry the defn context forward?

thheller 2026-04-29T15:02:18.635139Z

looks like that is a function that only runs during macro expansion? so *ns* should be fine no?

2026-04-29T15:03:15.422359Z

huh looks like you're correct, i didn't think about that

2026-04-29T15:05:22.862289Z

i think i was trying to avoid that because i've been seeing this error

8 | (defdescribe expectation-failed-test
-------^------------------------------------------------------------------------
An error occurred while generating code for the form.
ExceptionInfo: failed compiling constant: lazytest.expectation-failed-test; clojure.lang.Namespace is not a valid ClojureScript constant.
	cljs.compiler/fn--4209 (compiler.cljc:307)
	cljs.compiler/fn--4209 (compiler.cljc:304)
	clojure.lang.MultiFn.invoke (MultiFn.java:229)
	cljs.compiler/emit-constant-no-meta (compiler.cljc:286)
...

thheller 2026-04-29T15:05:50.003649Z

well yeah. use (ns-name *ns*) since you only want the string I presume

thheller 2026-04-29T15:06:24.334289Z

and put that function into a #?(:clj ...) so the CLJS compilation doesn't choke on that

👍 1