@allaboutthatmace1789 how's it going so far? How long have you been learning Clojure? you inspired me to learn more!!! awesome!
@claudius.nicolae I'll try to stick to emacs & (doom/spacemacs). I'm still in chapter 5 http://braveclojure.com, thanks a lot for the advice
Hi, I started clojure using leiningen for everything, managing my dependencies, and setuping my repl, packaging my app at the end... But I find it very rarely mentionned there, for the profit of deps.edn format. For a beginner like me, should I spend time to learn from deps also?
As a beginner, I would say that if Leiningen is doing what you need it to, there is no compelling reason to learn deps right away. It is worthwhile if you get to the point of contributing to a project that uses deps.edn, or you hit a project whose needs are not well served by Leiningen.
For basic managing of dependencies, there is a subset of what they both do that is nearly identical, i.e. listing project group/artifact names and versions published as JARs. Starting a REPL is also simply a little bit different, but quick to learn for both.
Honestly I think deps.edn is super useful particularly for beginners. Spinning up a simple repl and experimenting is so easy and low cost with deps.edn. I haven’t made a new lein project in years. Any experiment or play around or real project is deps.edn for me
I read the documentation for deps edn yesterday. Its not difficult at all to learn. I still need to practise but it did not cost me the time I expected. Maybe the reason is that Ihave more experience and deps edn is more focused.
Hi Clojurians - I’m struggling to get my repl to see a github-based java package. The package is here (https://github.com/whelk-io/flesch-kincaid) and I’m using git-down to get lein to import the dependency:
:dependencies [[org.clojure/clojure "1.10.0"]
[edu.stanford.nlp/stanford-corenlp "4.0.0"]
[io.whelk.flesch.kincaid/whelk-flesch-kincaid "0.0.31-RELEASE"]]
:git-down {io.whelk.flesch.kincaid/whelk-flesch-kincaid {:coordinates whelk-io/flesch-kincaid}
io.whelk.hy.phen/whelk-hy-phen-a-tion {:coordinates whelk-io/hy-phen-a-tion}}
lein pulls down the package just fine; when I try to import:
(import '(io.whelk.flesch.kincaid ReadabilityCalculator))
I get a ClassNotFoundException
exception. I can see the package in ~/.m2
so i suspect the problem is with leiningenYou should ensure that whatever makes you think that class exists in that library matches the version of that library that you are using
And I assumed you restarted your reply since adding that to your project.clj, but if you haven't you need to do that
I sum up @andy.fingerhut’s answer and yours as: both are doing the job for simple projects. But target is deps.edn. Is it only because it is the standard? or some advanced features are available only in deps.edn?
It looks like you might be using some weird lein plugin to add git dependency support
When I checked by myself I noticed no major difference, except that deps.edn is more "alive"
That almost certainly only works with clojure code
You can't use java straight up out of git, java needs to be compiled to classfiles first
One property of Leiningen that is sometimes given as a reason to prefer deps.edn is that Leiningen has a lot more hidden conventions that must be learned, that are not explicit until you learn about them. deps.edn does less in that regard. So in that sense deps.edn is simpler with fewer behaviors to work around, when you don't want those behaviors.
For small starter projects, I have a hard time imagining enough of a difference between their capabilities that one is strongly preferable.
When a project gets medium or large in complexity or needs, if those desires/needs differ from what Leiningen provides, it can be more challenging to learn to customize Leiningen to do what you need.
Caveat: This is me repeating things I've heard, not from personal experience. I have not worked on any projects that had complex needs for build/deploy/test/etc.
I started with Leiningen a decade ago because it was the only choice. I switched to Boot just over five years ago because I wanted more programmability in my build tooling but Boot was always pretty niche. I switched to the CLI / deps.edn
pretty much as soon as it appeared -- partly because it was the "official" tooling and partly because we were running into bugs and performance issues with Boot, given our very large codebase.
I find the CLI / deps.edn
tooling to be both very simple and very powerful. I recommend it to beginners because it's documented directly on http://clojure.org and it's likely to be the basis of more and more things that come out of Cognitect/Nubank.
But, yes, if you're happy using lein
-- and working with lein
-based projects and books/tutorials -- you might as well keep using it. You'll probably still need to learn the CLI / deps.edn
stuff at some point though: more and more libraries/projects are adopting it.
ok, I will continue with leiningen with my current project as it is already set. I'll move the project to CLI/`deps.edn` some times before production delivering, and before the next project. Thx
that’s the thing - the jars definitely exist:
l ~/.m2/repository/io/whelk/flesch/kincaid/whelk-flesch-kincaid/0.0.31-RELEASE/
total 72
drwxr-xr-x 7 jamierumbelow staff 224B 30 Jan 19:30 .
drwxr-xr-x 4 jamierumbelow staff 128B 30 Jan 19:27 ..
-rw-r--r-- 1 jamierumbelow staff 250B 30 Jan 19:30 _remote.repositories
-rw-r--r-- 1 jamierumbelow staff 19K 30 Jan 19:30 whelk-flesch-kincaid-0.0.31-RELEASE.jar
-rw-r--r-- 1 jamierumbelow staff 40B 30 Jan 19:30 whelk-flesch-kincaid-0.0.31-RELEASE.jar.sha1
-rw-r--r-- 1 jamierumbelow staff 2.7K 30 Jan 19:30 whelk-flesch-kincaid-0.0.31-RELEASE.pom
-rw-r--r-- 1 jamierumbelow staff 40B 30 Jan 19:30 whelk-flesch-kincaid-0.0.31-RELEASE.pom.sha1
and were put there by leinI am trying to reproduce what you are doing with a test Leiningen project on a Linux VM of mine, but when I include the :dependencies and :git-down keys in my project.clj
file, plus these line which the Leiningen git-down docs recommend (I haven't used it before, so I could be missing something:
(defproject try1 "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "<http://example.com/FIXME>"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "<https://www.eclipse.org/legal/epl-2.0/>"}
:dependencies [[org.clojure/clojure "1.10.0"]
[edu.stanford.nlp/stanford-corenlp "4.0.0"]
[io.whelk.flesch.kincaid/whelk-flesch-kincaid "0.0.31-RELEASE"]]
:git-down {io.whelk.flesch.kincaid/whelk-flesch-kincaid {:coordinates whelk-io/flesch-kincaid}
io.whelk.hy.phen/whelk-hy-phen-a-tion {:coordinates whelk-io/hy-phen-a-tion}}
:plugins [[reifyhealth/lein-git-down "0.4.0"]]
:repositories [["public-github" {:url "<git://github.com>"}]
["private-github" {:url "<git://github.com>" :protocol :ssh}]]
;;:repl-options {:init-ns try1.core}
)
When I try lein repl
in the directory of such a project, it fails to download the whelk-flesch-kincaid code, with messages like this:
Retrieving io/whelk/flesch/kincaid/whelk-flesch-kincaid/0.0.31-RELEASE/whelk-flesch-kincaid-0.0.31-RELEASE.pom from public-github
Retrieving io/whelk/flesch/kincaid/whelk-flesch-kincaid/0.0.31-RELEASE/whelk-flesch-kincaid-0.0.31-RELEASE.pom from public-github
Retrieving io/whelk/flesch/kincaid/whelk-flesch-kincaid/0.0.31-RELEASE/whelk-flesch-kincaid-0.0.31-RELEASE.jar from public-github
Retrieving io/whelk/flesch/kincaid/whelk-flesch-kincaid/0.0.31-RELEASE/whelk-flesch-kincaid-0.0.31-RELEASE.jar from public-github
Could not find artifact io.whelk.flesch.kincaid:whelk-flesch-kincaid:jar:0.0.31-RELEASE in central (<https://repo1.maven.org/maven2/>)
Could not find artifact io.whelk.flesch.kincaid:whelk-flesch-kincaid:jar:0.0.31-RELEASE in clojars (<https://repo.clojars.org/>)
Could not transfer artifact io.whelk.flesch.kincaid:whelk-flesch-kincaid:jar:0.0.31-RELEASE from/to public-github (<git://github.com>): <https://github.com/io.whelk.flesch.kincaid/whelk-flesch-kincaid>: Authentication is required but no CredentialsProvider has been registered
Could not transfer artifact io.whelk.flesch.kincaid:whelk-flesch-kincaid:jar:0.0.31-RELEASE from/to private-github (<git://github.com>): <https://github.com/io.whelk.flesch.kincaid/whelk-flesch-kincaid>: Authentication is required but no CredentialsProvider has been registered
Could not transfer artifact io.whelk.flesch.kincaid:whelk-flesch-kincaid:pom:0.0.31-RELEASE from/to public-github (<git://github.com>): <https://github.com/io.whelk.flesch.kincaid/whelk-flesch-kincaid>: Authentication is required but no CredentialsProvider has been registered
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.
Could not resolve dependencies
Given I've never used lein-git-down
, I am probably not configuring it correctly.
A jar existing doesn't mean anything
A jar is just a zip file, and can contain java source code just as easily as compiled class files
Well, it means something 🙂 Necessary, but not sufficient. The JAR needs to be on your JVM class path, which Leiningen often gets right, but might not be in your case. The JAR needs to contain compiled .class files defining the classes you are interested in, if it does not contain Clojure source code.
I haven't used this git down plugin, and I am not familiar with how it works, but my guess is it checks out the git repo, bundles it up as a jar, and sticks in m2 where leins normal dependency mechanism will find it
Which won't work if the project needs a "build" step like compiling java source to classfiles
You can use a command like unzip -v foo.jar
to see the contents of a jar file. I don't have it installed on the system I have handy at the moment, but most JDKs also install a command jar
that can be used for this purpose, perhaps with different command line options.
This code is a whole thing, but has a nice comment suggesting it does exactly as guessed https://github.com/reifyhealth/lein-git-down/blob/develop/src/lein_git_down/git_wagon.clj#L173
Strange - looks like you’ve configured it the same as I have
Although it does look like they do actually attempt to do a build step, but that seems like it could fail in all kinds of ways
This is really useful, thanks all
They may only handle build steps with maven in projects that use the clojure maven plugin
Okay – I’ve unzipped the jar and you’re correct, it’s just a handful of source files, nothing compiled
I guess then I need to compile the source separately. If I do that locally (say, in the directory above my clj project), can I tell lein to pull the dependency from there?
It is possible that library only distributes Java source files, and not pre-compiled JAR files.
Yep, I think that’s exactly what’s happened
I didn’t realise jars were (potentially) uncompiled!
If you find a way to compile and create a JAR file from that project, e.g. using the mvn command, its install
subcommand will typically create a JAR file containing compiled .class files in some place within your .m2
directory, and tell you the name of that JAR file near the last line of output.
Clojure JAR files often contain uncompiled Clojure/ClojureScript source code. For Java libraries, pre-compiled JAR files containing .class files are definitely most common. JAR files are like zip or tar files -- they can contain any kinds of files inside.
Is there a community-driven ‘interop’ site that compiles and wraps common Java libraries, similar to eg cljsjs, or definitely-typed in typescript-land? I’m surprised that lein can’t compile this stuff for me
It’s very unusual not to distribute Java libs as compiled jars in Maven repos
Say I have a map, {:a 1 :b 2 :c 3}
, I was wondering if one of the cond
variations would destructure and test if the value is null, so that I could execute a branch of code once the first non-nil value is hit. A bit like this
(def foo {:a 1 :b 2 :c 3})
(condp not nil? foo
a (branch-1 a)
b (branch-2 b)
c (branch-3 c))
natch, that's bad code, but is there an idomatic way of doing that in Clojure?
@dharrigan Given that hash maps are inherently unordered, you'd have to provide an ordered list of keys to check, no?
(although, in this case you also have an inherent order of functions to call on specific keys' values)
Yes, this library does not have any pre-compiled JARs on Maven Central according to search at Maven Central: https://search.maven.org/
That is unusual.
It is also an extra step for the publisher of the Java code to go through, which many do, but it isn't automatically done for them.
You're absolutely right! I keep forgetting they are unordered!
d'oh
I can do something like this
(def foo {:a nil :b 2 :c 3})
(when-let [{:keys [a b c]} foo]
(cond
a "x"
b "y"
c "z"))
That said, if you have a hash map of data and a hash map from keys in that data to functions to apply to them and a vector of keys in order to check... then a reduce
would work...
(def foo {:a nil :b 2 :c nil})
(when-let [{:keys [a b c]} foo]
(cond
c "z"
a "x"
b "y"
:else "bedtime!")) ;; "y"
that seems to work nicely! 🙂
(def foo {:a nil :b 2 :c nil})
(def foo-fn {:a branch1 :b branch-2 :c branch-3})
(reduce (fn [_ k] (when-let [v (k foo)] ((k foo-fn) v)))
nil
[:a :b :c])
That was the generalization I was suggesting.oooh
I like that too
going to save that in my "Sean's Snippets" folder... 🙂
I guess another option is first
of for
: (first (for [k [:a :b :c] :let [v (k foo)] :when v] ((k foo-fn) v)))
🙂 Another useful one. Thank you Sean. For me bedtime!
ttfn!