Search code examples
clojureleiningen

lein repl error "Unable to resolve symbol: str in this context"


I'm new to clojure. I'm facing below error -

I created a new lein project using command lein new app clj-lein-app-project.

The project is on github.

Then I created new namespace ns-playground.hello as in here.

The contents of hello.clj is -

(ns ns-playground.hello
  (:import [java.util Date]))

(def addition +)

(defn current-date []
  "this function returns the current date"
  (new Date))

Then I launched the repl using command lein repl -

In repl I did (str "Hello""""world") and (for [el ["element1""element2""element3"]] el) which are working fine.

Then I changed the namespace to ns-playground.hello using command (in-ns 'ns-playground.hello). Now I did (str "Hello""""world") and (for [el ["element1""element2""element3"]] el) but I got below error -

Syntax error compiling at (/private/var/folders/7v/gp_j1tf92xx3m8gxltryr_bmzdys_4/T/form-init6109117777235064500.clj:1:1).

Unable to resolve symbol: for in this context

enter image description here

How the clojure code is not working in different namespace in lein repl?


Solution

  • https://clojure.org/guides/repl/navigating_namespaces

    explains it: If you switch to a namespace, which you previously in your session did not decalred with (ns ...), but instead directly enter to it via (in-ns ...) this kind of behavior occurs. You can't then use clojure.core's symbols even.

    What happens if you in-ns to a namespace that has never been created? You will see strange things happening. For instance, you will not be able to define a function using defn:

    $ clj Clojure 1.10.0 user=> (in-ns 'myapp.never-created)
    #object[clojure.lang.Namespace 0x22356acd "myapp.never-created"] myapp.never-created=> (defn say-hello [x] (println "Hello, " x "!"))
    Syntax error compiling at (REPL:1:1). Unable to resolve symbol: defn
    in this context
    

    Explanation: in this situation, in-ns creates the new namespace and switches to it like ns does, but it does a little less work than ns, because it does not automatically make available all the names defined in clojure.core, such as defn. You can fix that by evaluating (clojure.core/refer-clojure):

    > myapp.never-created=> (clojure.core/refer-clojure) nil
    > myapp.never-created=> (defn say-hello [x] (println "Hello, " x "!"))
    > #'myapp.never-created/say-hello myapp.never-created=> (say-hello "Jane") Hello,  Jane ! nil
    

    If you only use in-ns to switch to namespaces that have already been created, you won’t have to deal with these subtleties.

    So either you didn't defined your namespace before entering it. Or you became a victim of a typo when entering your namespace.

    So if you entered a typo-namespace but are too lazy to correct the typo, then just refer by

    (clojure.core/refer-clojure)
    

    Theoretically, you could always attach clojure.core/ before every symbol - e.g. clojure.core/for then it should work - but maybe this is too tedious.