Fork me on GitHub
#graalvm
<
2023-04-03
>
igrishaev12:04:44

Can anyone give me a hint on how to use the *ns* dynamic variable in native image? Imagine I have a macro for logging:

(defmacro logf [level template & args]
  `(println (ns-name *ns*)
            (-> ~level name str/upper-case)
            (format ~template ~@args)))
In repl, it renders the corresponding ns like my.project.utils INFO ... . But when running a binary file, I see clojure.core INFO everywhere. Is it even possible with native image?

borkdude12:04:25

Maybe you need to pull the ns deref to compile time outside of the expansion!

igrishaev12:04:56

hm, do you mean an atom or a defer?

borkdude14:04:45

@U1WAUKQ3E I mean:

(defmacro logf [..] (let [nsn (ns-name *ns*)] `(println ... ~nsn)))
Not sure if that would help

igrishaev14:04:21

hm, good idea, let me try

igrishaev16:04:43

You were right! Here is the final version of my logging ns:

(ns lambda-demo.log
  (:require
   [clojure.string :as str]))


(defmacro logf [level template & args]
  (let [nsn (ns-name *ns*)]
    `(println '~nsn
              (-> ~level name str/upper-case)
              (format ~template ~@args))))


(defmacro debugf [template & args]
  `(logf :debug ~template ~@args))


(defmacro infof [template & args]
  `(logf :info ~template ~@args))


(defmacro errorf [template & args]
  `(logf :error ~template ~@args))