Opening leiningen project in emacs/cider raises classpath error - cider

I'm learning Clojure with 'Clojure for the Brave and True' book and use emacs, cider and leiningen. I've created a project.
lein new app the-divine-cheese-code
Then I've added to source files to the project.
the-divine-cheese-code\src\the_divine_cheese_code\core.clj
the-divine-cheese-code\src\the_divine_cheese_code\visualization\svg.clj
In 'core.clj' I refer to the 'svg.clj' namespace.
the-divine-cheese-code\src\the_divine_cheese_code\core.clj
(ns the-divine-cheese-code.core)
;; Ensure that the SVG code is evaluated
(require 'the-divine-cheese-code.visualization.svg)
;; Refer the namespace so that you don't have to use the
;; fully qualified name to reference svg functions
(refer 'the-divine-cheese-code.visualization.svg)
(def heists [{:location "Cologne, Germany"
:cheese-name "Archbishop Hildebold's Cheese Pretzel"
:lat 50.95
:lng 6.97}
{:location "Zurich, Switzerland"
:cheese-name "The Standard Emmental"
:lat 47.37
:lng 8.55}
{:location "Marseille, France"
:cheese-name "Le Fromage de Cosquer"
:lat 43.30
:lng 5.37}
{:location "Zurich, Switzerland"
:cheese-name "The Lesser Emmental"
:lat 47.37
:lng 8.55}
{:location "Vatican City"
:cheese-name "The Cheese of Turin"
:lat 41.90
:lng 12.45}])
(defn -main
[& args]
(println (points heists)))
the-divine-cheese-code\src\the_divine_cheese_code\visualization\svg.clj
(ns the-divine-cheese-code.visualization.svg)
(defn latlng->point
"Convert lat/lng map to comma-separated string"
[latlng]
(str (:lat latlng) "," (:lng latlng)))
(defn points
[locations]
(clojure.string/join " " (map latlng->point locations)))
Here is the project's entire dir structure.
the-divine-cheese-code
the-divine-cheese-code\.gitignore
the-divine-cheese-code\.hgignore
the-divine-cheese-code\.nrepl-port
the-divine-cheese-code\CHANGELOG.md
the-divine-cheese-code\doc
the-divine-cheese-code\doc\intro.md
the-divine-cheese-code\LICENSE
the-divine-cheese-code\project.clj
the-divine-cheese-code\README.md
the-divine-cheese-code\resources
the-divine-cheese-code\src
the-divine-cheese-code\src\the_divine_cheese_code
the-divine-cheese-code\src\the_divine_cheese_code\core.clj
the-divine-cheese-code\src\the_divine_cheese_code\visualization
the-divine-cheese-code\src\the_divine_cheese_code\visualization\svg.clj
the-divine-cheese-code\target
the-divine-cheese-code\target\default
the-divine-cheese-code\target\default\classes
the-divine-cheese-code\target\default\classes\META-INF
the-divine-cheese-code\target\default\classes\META-INF\maven
the-divine-cheese-code\target\default\classes\META-INF\maven\the-divine-cheese-code
the-divine-cheese-code\target\default\classes\META-INF\maven\the-divine-cheese-code\the-divine-cheese-code
the-divine-cheese-code\target\default\classes\META-INF\maven\the-divine-cheese-code\the-divine-cheese-code\pom.properties
the-divine-cheese-code\target\default\repl-port
the-divine-cheese-code\target\default\stale
the-divine-cheese-code\target\default\stale\leiningen.core.classpath.extract-native-dependencies
the-divine-cheese-code\test
the-divine-cheese-code\test\the_divine_cheese_code
the-divine-cheese-code\test\the_divine_cheese_code\core_test.clj
When I run the project with 'lein run' it executes successfully. However, when I open the core.clj file with emacs/cider and try to compile it, I get classpath error.
CompilerException java.io.FileNotFoundException: Could not locate
the_divine_cheese_code/visualization/svg__init.class or
the_divine_cheese_code/visualization/svg.clj on classpath. Please check
that namespaces with dashes use underscores in the Clojure file name.,
compiling:(c:/temp/the-divine-cheese-code/src/the_divine_cheese_code/core.clj:2:1)
CIDER compiles sources sucessfully if I put them in the same directory (changing namespace correspondingly).
(ns the-divine-cheese-code.core)
(require 'the-divine-cheese-code.svg)
(refer 'the-divine-cheese-code.svg)
(def heists [{:location "Cologne, Germany"
...
So maybe the issue is dealt with OS. I use Windows 7, which is not primary OS for Emacs/CIDER.
After some experimenting I found that the CIDER works without :refer
(ns the-divine-cheese-code.core
(:require [the-divine-cheese-code.visualization.svg]))
This looks like a CIDER bug and 'lein run' predictably gives error in this case.
If I make it the right way
(ns the-divine-cheese-code.core
(:require [the-divine-cheese-code.visualization.svg :refer :all]))
the CIDER now gives another error:
Caused by java.lang.IllegalStateException
latlng->point already refers to:
#'the-divine-cheese-code.svg/latlng->point in namespace:
the-divine-cheese-code.core

Would suggest to use the options provided by the ns macro instead of naked require and refer statements - this is the recommended way of doing imports/requires in Clojure and most of the tooling is written with this way of managing namespaces in mind. Even if the below code still doesn't work in CIDER, it will be easier to diagnose it:
;; the-divine-cheese-code\src\the_divine_cheese_code\core.clj
(ns the-divine-cheese-code.core
(:require [the-divine-cheese-code.visualization.svg :refer :all]))
(def heists ...)
(defn- main ...)

In my case, the error went away after I renamed (to the same name) src/the_divine_cheese_code/ folder and it's contents recursively.
Not sure what caused the issue. My guess is that character encoding was screwed up. I created both the file and folder in Emacs and done the renaming in Double Commander.

Related

How to implement *load-fn* for :requires in bootstrapped clojurescript

(ns scratch
(:require [cljs.js :as cjs]))
;Let's setup a simple clojurescript string eval that supports namespaces:
(def current-ns 'cljs.user)
(def compiler-state (cjs/empty-state))
(defn eval-text [text]
(println string)
(cjs/eval-str compiler-state text current-ns
{:eval cjs/js-eval
:ns current-ns
:context :expr
:def-emits-var true}
(fn [result]
(set! current-ns (:ns result))
(println result))))
(eval-text "(ns a.a)")
(eval-text "(defn add [a b] (+ a b))")
(eval-text "(add 4 4)")
;I can refer to the function from another namespace explicitly with no problem
(eval-text "(ns x.x)")
(eval-text "(a.a/add 6 6)")
;However when I do
(eval-text "(ns b.b (:require [a.a :refer [add]]))")
On the last line I get:
{:error #error {:message Could not require a.a, :data {:tag :cljs/analysis-error}, :cause #object[Error Error: No *load-fn* set]}}
So I have to create my own https://cljs.github.io/api/cljs.js/#STARload-fnSTAR
and pass it into the :load compiler option to handle this :require even though the compiler state already knows about my namespace as I can call the fully qualified function from another namespace.. Correct?
What is the best way to do that?
Should I create maps that store namespace->source-code from previously evaled code and get namespace->analysis-cache from the compiler state and pass these into the :source and :cache callbacks of my custom load function?
Is there a better / more efficient way to do this?
I believe I found the answer:
The :load option of eval-str can be set to the following function:
(defn load-dep [opts cb]
(cb {:lang :js :source ""})
And it will quite happily resolve. This isn't really apparent from the documentation that the callback can return this value when the namespace/var is already in the compiler state so I'll leave the question here.

Clojure: create function whose name is given as a parameter at run-time

I'm trying to create a Clojure function, that returns another function with a custom name. My attempts so far:
(defn function-with-custom-name [name] (fn name [] 42))
(function-with-custom-name "hello")
# --> #object[lang.main$function_with_custom_name$name__4660 0xa6afefa "lang.main$function_with_custom_name$name__4660#a6afefa"]
# syntactically ok, but its name is 'name' and not 'hello'
(defn function-with-custom-name [name] (fn (symbol name) [] 42))
# --> CompilerException java.lang.IllegalArgumentException: Parameter declaration symbol should be a vector, compiling:(/tmp/form-init3365336074265515078.clj:1:40)
(defn function-with-custom-name [name] (fn '(symbol name) [] 42))
# --> CompilerException java.lang.IllegalArgumentException: Parameter declaration quote should be a vector, compiling:(/tmp/form-init3365336074265515078.clj:1:40)
I understand that fn is a macro, and therefore proper quoting is probably important for the parameter, but as per above, I could not get it right, but I'm 99% sure there is a way, since (looking at the source of fn), the only criteria is that the first parameter should be recognized as a symbol.
Any hints on how to do this?
EDIT: Use-case, as asked in the comment: I'm writing a simple language interpreter in Clojure, which (among other things) lets you create functions. The functions from my language are currently represented by anonymous Clojure functions. However, it would make debugging the interpreter much easier, if the Clojure functions also did have a name.
EDIT2: The first edit made me think, and I came to the conclusion that I cannot use macro-based solutions for this problem, since I need to create the functions run-time (and, as far as I remember, macros can only work at compile-time). --> Changed the question title for clarity. Still, please don't delete the macro-based answers, since they give helpful insight.
You can use defmacro.
(defmacro function-with-custom-name [name]
`(fn ~(symbol name) ([] 42)))
you can also do it in runtime, without using macros, using namespace functions instead. It can give you the way to register functions from some input for example (i can't really find any good reason for this though, but maybe it's just me)
user> (defn runtime-defn [f-name f]
(intern (ns-name *ns*) (symbol f-name) f))
#'user/runtime-defn
user> (runtime-defn "my-fun" #(* 100 %))
#'user/my-fun
user> (my-fun 123)
;;=> 12300
user> (runtime-defn (read) #(* 200 %))
#input "danger!!!"
#'user/danger!!!
user> (danger!!! 1)
;;=> 200
Update:
For the simple version, you can use defmacro. For a more complicated version (such as used by the potemkin library) you need to mess around with creating a var and "intern-ing" it into the clojure namespace. This is accomplished via clojure.core/intern:
(ns tst.demo.core
(:use demo.core tupelo.test )
(:require [tupelo.core :as t] ))
(t/refer-tupelo)
(defmacro make-fn-macro-unquote [name]
(spyxx name)
`(defn ~name [] 42))
(defn make-fn-func-quote [name2]
(spyxx name2)
(intern 'tst.demo.core (symbol name2) (fn [] 43)))
(dotest
(make-fn-macro-unquote fred)
(spyxx fred)
(is= 42 (spyx (fred)))
(let [wilma-var (make-fn-func-quote "wilma")]
(spyxx wilma-var)
(is= 43 (spyx (wilma-var)))))
Look at the output:
name => clojure.lang.Symbol->fred
fred => tst.demo.core$fn__38817$fred__38818->#object[tst.demo.core$fn__38817$fred__38818 0x5f832a1 "tst.demo.core$fn__38817$fred__38818#5f832a1"]
(fred) => 42
name2 => java.lang.String->"wilma"
wilma-var => clojure.lang.Var->#'tst.demo.core/wilma
(wilma-var) => 43
Note that fred is a clojure function, while wilma-var is a clojure var. Please see this post on the relationship between a symbol like foo and a var and a function.
Note also that the macro version takes an unquoted symbol fred as input, while the function version takes a plain string in double-quotes as input.
So fred is a symbol pointing to a function, while wilma-var is a symbol pointing to a var (which then points to a function). In either case, Clojure allows us to type (fred) or (wilma-var) to make a function call, and we get either 42 or 43 as a result.

How to 'turn on' cljs.spec

How do I make sure that clojure/cljs.spec is verifying function call arguments and return values?
Say I have this function:
(defn my-inc [x]
(inc x))
After which I have this:
(s/fdef my-inc
:args (s/cat :x number?)
:ret number?)
This code compiles because [cljs.spec.alpha :as s] has been required.
Now I call the function so as to hopefully generate an error:
(my-inc "Not a number")
I would like to see the fdef being used, and see the error message stating that my-inc cannot be called with a string. How do I make this happen in a very general way, for instance with a setting in project.clj or user.cljs?
With this code in user.cljs:
(:require
[cljs.spec.alpha :as s]
[cljs.spec.test.alpha :as ts])
(defn my-inc [x]
(inc x))
(s/fdef my-inc
:args (s/cat :x number?)
:ret number?)
(ts/instrument)
(defn x-1 []
(my-inc "Hi"))
I can call x-1 from the cljs/figwheel REPL, and get this failure message:
#error {:message "Call to #'cljs.user/my-inc did not conform to spec:\nIn: [0] val: \"Hi\" fails at: [:args :x] predicate: number?\n:cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha50572]\n:cljs.spec.alpha/value (\"Hi\")\n:cljs.spec.alpha/args (\"Hi\")\n:cljs.spec.alpha/failure :instrument\n", :data #:cljs.spec.alpha{:problems [{:path [:args :x], :pred cljs.core/number?, :val "Hi", :via [], :in [0]}], :spec #object[cljs.spec.alpha.t_cljs$spec$alpha50572], :value ("Hi"), :args ("Hi"), :failure :instrument}}
I can also get conformance errors when working with a real project running code in a browser. The errors show up in the developer's console on the browser.
Put (ts/instrument) at the bottom of user.cljs to turn instrumentation on for all namespaces for development.
Edit
Just in case you are hit by this problem: https://dev.clojure.org/jira/browse/CLJS-1792
- the fix is to include [org.clojure/test.check "0.10.0-alpha2"] (probably with a more recent version) in your project.clj dependencies.
You can use instrument to check args conformance for certain symbols or all vars.
When called without arguments, instrument wraps all instrumentable vars into a function that checks the args before delegating to the original function.

Loading Clojure.core.match

I'm new to Clojure and I'm wanting to use Clojure core.match:
https://github.com/clojure/core.match
I've setup my project with TextMate using the following bundle: https://github.com/swannodette/textmate-clojure
My project.clj is as follows:
(defproject Prototype "0.0.1-SNAPSHOT"
:description "Prototype ARS Implementation"
:dependencies [[clojure "1.3.0"] [org.clojure/core.match "0.2.0-alpha6"]])
In terminal, I executed:
cake deps
Which downloaded the correct version of Clojure and the Clojure.core.match jar files.
Now I'm editing my 'src/Prototype/core.clj' and I'm wanting to use the match functionality.
I've tried using both the provided code on the GitHub page:
;; when using HEAD
(use '[clojure.core.match :only [match]])
;; when using the latest released alpha
(use '[clojure.core.match.core :only [match]])
This is my current code:
(ns Prototype.core
(use '[clojure.core.match.core :only [match]]))
(println
(let [x [1 2]]
(match [x]
[[1 2]] "It worked!"
:else "It failed!")))
When I load the file into the cake repl; I get the following error:
lib names inside prefix lists must not contain periods
Any ideas?
Cheers.
(ns Prototype.core
(:use [clojure.core.match.core :only [match]]))
(println
(let [x [1 2]]
(match [x]
[[1 2]] "It worked!"
:else "It failed!")))
There's no need to quote in the ns form.
(I've assumed clojure.core.match.core was the correct namespace. If it doesn't work use clojure.core.match instead.)

Can I refer another namespace and expose its functions as public for the current ns?

I thought use would do it but it seems the mapping created in the current namespace is not public. Here is an example of what I'd like to achieve:
(ns my-ns
(:use [another-ns :only (another-fct)]))
(defn my-fct
[]
(another-fct 123)) ; this works fine
Then I have another namespace like this:
(ns my-ns-2
(:require [my-ns :as my]))
(defn my-fct-2
[]
(my/another-fct 456)) ; this doesn't work
I would like to do that because another-ns is a library to access a database. I would like to isolate all the calls to this library in a single namespace (my-ns), this way all the DB dependent functions would be isolated in a single namespace and it becomes easier to switch to another DB if needed.
Some of the functions of this library are just fine for me but I'd like to augment others. Let's say the read functions are fine but I'd like to augment the write functions with some validation.
The only way I see so far is to hand-code all the mapping into my-ns even for the functions I don't augment.
One way to do this selectively (specifying each function explicitly) is to use something like Zach Tellman's Potemkin library. An example of it's use is found in the lamina.core namespace which serves as the public entry point for Lamina, importing the key public functions from all other internal namespaces.
You can also use clojure.contrib.def/defalias:
(use 'clojure.contrib.def/defalias)
(defalias foo clojure.string/blank?)
(foo "")
Does this help?
(defmacro pull [ns vlist]
`(do ~#(for [i vlist]
`(def ~i ~(symbol (str ns "/" i))))))
Here's an example:
(ns my-ns)
(defmacro pull [ns vlist]
`(do ~#(for [i vlist]
`(def ~i ~(symbol (str ns "/" i))))))
(pull clojure.string (reverse replace))
(defn my-reverse
[]
(reverse "abc"))
(ns my-ns-2)
(defn my-fct-2 []
(list (my-ns/my-reverse)
(my-ns/reverse "abc")))
(my-fct-2)
If you want to just pull in everything, then:
(defmacro pullall [ns]
`(do ~#(for [i (map first (ns-publics ns))]
`(def ~i ~(symbol (str ns "/" i))))))
(pullall clojure.string)
To pull everything from namespace that may have macros defined within use this
(defmacro pullall [ns]
`(do ~#(for [[sym var] (ns-publics ns)]
`(def ~sym ~var))))