What is the proper way to use a dependency? - clojure

Maybe I'm missing something or just reading outdated information. Basically, I'm trying to use the CSV lib here.
I've included it in my project.clj...
:dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/data.csv "0.1.2"]]
...and retrieved the libs successfully using Leiningen. Now, what would be the proper way to include this lib for use in my program? I've tried the example posted on the lib's Github page only to get an error stating:
FileNotFoundException Could not locate clojure/data/csv__init.class or clojure/data/csv.clj on classpath: clojure.lang.RT.load (RT.java:430)
EDIT: Further clarification on what I've tried: I have the code pasted under my namespace declaration, like so:
(ns testprogram.core(:gen-class))
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io])
Trying it in the REPL yields the same result. I'm pretty sure I'm trying to 'include' them wrong.

This test worked for me:
(ns test.csv-test
(:gen-class)
(:require [clojure.data.csv :as csv]
[clojure.java.io :as io]))
(defn main- [args]
(csv/read-csv "test"))
I also encountered the "FileNotFound: could not locate" issue while testing this out. It was a simple typo in my project.clj file. I recommend double-checking that.
Note: this also worked:
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io])
(defn main- [args]
(csv/read-csv "test"))
While using the :require directive in the ns macro is certainly a best practice, is is not the source of the issue here.
In both versions, REPL output:
user=> (in-ns 'test.csv-test)
#<Namespace test.csv-test>
test.csv-test=> (main- [])
(["test"])
Also tested with lein run and java -cp <uberjar> test.csv_test

You could try the following: note the :require is nested within the ns declaration. This is the preferred way of doing it.
(ns testprogram.core(:gen-class)
(:require [clojure.data.csv :as csv]
[clojure.java.io :as io]))
I think in your case you can get it to work with the following (not tested)
(ns testprogram.core(:gen-class))
(require '(clojure.data [csv :as csv])
'(clojure.java [io :as io]))
See the following desc
http://clojure.github.com/clojure/clojure.coreapi.html#clojure.core/require

Related

Loading external library in clojure

{:deps
com.google.code.gson/gson {:mvn/version "2.9.0"}}
}
in core.clj: evaluate
(ns core
(:require [google.code.gson/gson :refer :all]
)
(:gen-class))
I get exception:
Unhandled clojure.lang.Compiler$CompilerException
Call to clojure.core/ns did not conform to spec.
I just want to load gson into my namespace. What am i doing wrong?
Group/Artifact coordinates (what you are using to resolve dependencies;
e.g. com.google.code.gson/gson) are not related to what is in
those artifacts. So you can not just require the artifact. You have to
require the namespaces of what is in them or more likely in this case
import the classes that are in them (it's a java library more likely
and not a Clojure library).
The error you get there is due to the / in the require. And even if
you the needed . instead you will see an error, that no such namespace
exists.
(ns core
(:gen-class))
(import [com.google.gson Gson])
seems to work.
But why do not need the code part in com.google.code.gson?

How to add the clojure.string library to a front-end Hoplon project using the Boot-clj build tool

I hope these questions are helping someone. I am new to both Hoplon and Boot. I am trying to use the "clojure.string" library in a Hoplon project and I can't seem to get it. I tried in the index.cljs.hl file:
(:require [clojure.string :as str]))
And then it doesn't load. Next I tried including the library in the build.boot tool but neither seemed to work:
[org.clojure/clojure.string "1.8.0"]
[org.clojure/clojure-string "1.8.0"]
Neither of those seemed to work so I am looking on how I can use the string library.
Cheers,
Matt
After much searching I finally figured out how to do it. All you need to do is in the "index.cljs.hl" file add the following at the top.
(page "index.html"
(:require [clojure.string :as str]))
And then you can access the string library as (str/split etc.
Cheers,
Matt

Leiningen keeps old defns

I have very strange Lein's behavior: it keeps loading unexisting old code.
There is src directory with something like src/service/api.clj and src/user.clj. All files under src/service are reloading, but lein totally ignores any changes in src/user.clj.
(ns user
(:require [ragtime.jdbc :as jdbc]
[ragtime.repl :as repl]))
...
(defn migrate []
(repl/migrate (load-config)))
Even if I delete migrate definition, REPL will have it in user namespace, lein will run it with lein run -m user/migrate after doing lein clean and will not load changes with (load-file "src/user.clj") too.
How to make it load my changes to user.clj ?
Lein only looks for code in source paths directories. If you don't have any specified then src is assumed. In your project.clj this would be the suggested entry:
:source-paths ["dev" "src"]
To be able to reload code from the REPL this will work for user.clj:
(ns user
(:require [clojure.tools.namespace.repl :refer (refresh refresh-all)]
[clojure.stacktrace]
[clojure.pprint :as pp]))
;;
;; To run open a REPL and:
;; (reset)
;; (core/migrate)
;; Repeat those two commands after every source code change you make
;;
(defn reset []
(refresh))
user.clj can go under the dev directory.
The answer to your question is I think that user.clj is supposed to be changed so infrequently that restarting the JVM/REPL is not an issue after you have made changes. Code that is being changed frequently should be under the src directory, and should not be named as namespace user. The main entry point code that you have typically goes in a file called core.clj. So you should put the contents of your user.clj file in the core namespace i.e. in a file called core.clj, which is placed under src.

Dependencies downloaded but still cannot require, clojure

This kills me... I cannot require anything other than built-in native deps. No hiccup, no http-kit etc... Even if I can find them on my hard drive in .m2/repository
lein new myapp,
add [markdown-clj 0.9.91] to project.clj,
add (ns metapp.core
(:require [markdown-clj :as mark]) )
lein run
Retrieving markdown-clj/markdown-clj/0.9.91/markdown-clj-0.9.91.pom from clojars
Retrieving markdown-clj/markdown-clj/0.9.91/markdown-clj-0.9.91.jar from clojars
Exception in thread "main" java.io.FileNotFoundException: Could not locate quote/markdown_clj__init.class or quote/markdown_clj.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.,
lein deps is not returning anything
Somebody knows what's wrong please? This stacktrace isn't very helpful, so Lein can fetch deps, but doesn't know how to require them?
EDIT: Running Linux Mint 18.0, clojure is in /home/denis/clojure-1.8.0 and is called by alias java -cp /home/denis/clojure-1.8.0/clojure-1.8.0.jar clojure.main. Directory tree in myapp is /home/denis/prg/cljr/myapp
SOLUTION:
Thank you guyz, but now feel like an idiot.
So to summarize for future-comers, in project.clj, to ask for a dependency "X" doesn't mean you should "require" it as "X". You must require it the way the author specified in documentation, for example [http-kit "2.2.0"] in project.clj is required as follows
(ns metapp.core (:require [org.httpkit.client :as http] ).
Second, the way you require inside your code is not the same as the way you require in REPL, for example, this works in yourapp.core (require [stuff.core as stuff]). You could also write it like this, it works too (ns yourns (:require [stuff.core :as stuff]). But this synthaxe doesnt work: (:require [stuff.core :as stuff]).
In REPL however, it's different story! I must use (:require '[stuff.core]) if it is an added dependency, or (:require 'clojure.string) if it is a built-in library! Note that something like (require '[http.async.core]) doesn't work because it is not built-in. So if you checked the documentation https://clojuredocs.org/clojure.core/require which only shows built-in examples, like me, you are doomed.
Also for built-in library like clojure.string you can use simply (require 'clojure.string), yup, the one which didn't worked with dependencies. Have fun guys! LOOOOONNG journey ahead, clojure is only language so far I needed to spend 4 days figuring out how to IMPORT modules (poke Python, it only took 30 seconds), hope it worth it!
You should require markdown.core. From the documentation for that project:
(ns foo
(:use markdown.core))
In your case:
(ns metapp.core
(:require [markdown.core :as mark]))
should work.
Not realising that the name of the library and the namespaces that make up the library are different things is something that is easy to be tripped up by.
markdown-clj is just a name of a package. But when you require something, you need to specify a module, not a package. Most of the packages have core module so the proper usage would be:
(:require [markdown-clj.core :as mark])

requiring namespaces in clojure leinengen project

I'm new with clojure and the jvm and am having trouble creating a leinengen project where I can separate my code into namespaces. My project is named cloj_test and in my cloj_test/src/cloj_test directory I have a file named db_connect.clj. In the db_connect.clj file I have code at the top to define the namespace
(ns db-connect
(:require [clojure.java.jdbc :as jdbc]
[clojure.java.jdbc.sql :as sql]))
and then a few functions to define some database functionality. cloj_test/src is on the lein classpath. When I launch the repl using "lein repl" and then type
(require 'cloj-test.db-connect)
It works. However, if I type
(require '[cloj-test.db-connect :as db])
I get this error:
Exception namespace 'cloj-test.db-connect' not found clojure.core/load-lib (core.clj:5380)
The same thing happens when I use "use". Does anybody know how I can resolve this?
The package name is missing form the ns declaration
(ns cloj-test.db-connect
(:require [clojure.java.jdbc :as jdbc]
[clojure.java.jdbc.sql :as sql]))
The namespace declaration needs to match the directory that the file is in
(except that -s are changed to _s) in the file and directory names.