Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pre define vars before loading namespace

Tags:

clojure

I have a namespace called some.core with the following,

(ns some.core)
(defonce name-of-something :a)

then from a leiningen plugin I would like to predefine name-of-something before loading the namespace so that when the namespace is loaded it is already defined defonce won't define it.


    (eval-in-project project
                     `(do (create-ns 'some.core)
                          (intern 'some.core 'name-of-something :b)))

but with the above I keep getting,

Can't intern namespace-qualified symbol

error.

like image 947
Hamza Yerlikaya Avatar asked Aug 22 '26 15:08

Hamza Yerlikaya


1 Answers

(Updated to take into account the comments below. I leave the original answer under the horizontal rule so as not to remove the context of the comments.)

TL;DR fix:

`(do ... (intern 'some.core '~'name-of-something :b))
                          ; ^- note the '~'

The problem is that the (do ...) form is syntax-quoted (quoted with a backtick, as opposed to a single quote), so symbols inside it get replaced with namespace-qualified variants (after being resolved to determine which namespace they should be qualified with). This excludes symbols which are already namespace-qualified as well as those which contain a dot.

The problematic symbol in the above is name-of-something -- dot-free and unqualified. To rectify the situation, you can replace 'name-of-something with '~'name-of-something; the first quote is included in the output of syntax-quote, the tilde causes the value of the form immediately following it to be included in the expansion of the syntax-quoted region and finally 'name-of-something is the form itself, evaluating to the (unqualified) symbol name-of-something:

If unquoting was unnecessary, replacing the backtick with a single quote would also solve the problem. (The final solution -- mentioned for completeness -- would be to build the form manually: (list 'do ...).)


(Original answer follows.)

You need to change the backtick to single quote:

`(do (create-ns 'some.core) ...)
; change to
'(do (create-ns 'some.core) ...)
^- note the quote

What happens with the backtick, or "syntax quote", is that 'name-of-something gets munged to 'current-namespace/name-of-something, causing intern to complain. (Note that some.core stays untouched -- due to magic treatment of dots in symbols, I believe. The other symbols -- do, create-ns and intern -- are also replaced with namespace-qualified variants, but that doesn't cause any problems.)

like image 52
Michał Marczyk Avatar answered Aug 24 '26 11:08

Michał Marczyk