beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-01-30T04:07:01.193200Z

@allaboutthatmace1789 how's it going so far? How long have you been learning Clojure? you inspired me to learn more!!! awesome!

2021-01-30T04:08:51.193400Z

@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

caumond 2021-01-30T19:34:42.200200Z

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?

2021-01-30T19:39:15.200300Z

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.

2021-01-30T19:41:05.202800Z

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.

dpsutton 2021-01-30T19:41:35.203800Z

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

caumond 2021-02-04T06:18:36.461Z

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.

Jamie Rumbelow 2021-01-30T19:47:16.205Z

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}}

Jamie Rumbelow 2021-01-30T19:48:15.206200Z

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 leiningen

2021-01-30T19:52:10.207600Z

You should ensure that whatever makes you think that class exists in that library matches the version of that library that you are using

2021-01-30T19:54:14.208700Z

And I assumed you restarted your reply since adding that to your project.clj, but if you haven't you need to do that

caumond 2021-01-30T19:54:29.208800Z

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?

2021-01-30T19:55:19.210300Z

It looks like you might be using some weird lein plugin to add git dependency support

caumond 2021-01-30T19:55:41.210900Z

When I checked by myself I noticed no major difference, except that deps.edn is more "alive"

2021-01-30T19:55:48.211200Z

That almost certainly only works with clojure code

2021-01-30T19:56:24.212200Z

You can't use java straight up out of git, java needs to be compiled to classfiles first

2021-01-30T19:56:46.212300Z

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.

👍 2
2021-01-30T19:57:57.212500Z

For small starter projects, I have a hard time imagining enough of a difference between their capabilities that one is strongly preferable.

2021-01-30T19:59:23.212700Z

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.

2021-01-30T20:00:02.212900Z

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.

seancorfield 2021-01-30T20:04:34.213100Z

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.

seancorfield 2021-01-30T20:07:07.213400Z

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.

seancorfield 2021-01-30T20:08:06.213600Z

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.

caumond 2021-01-30T20:10:49.213800Z

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

Jamie Rumbelow 2021-01-30T20:16:57.214300Z

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 lein

2021-01-30T21:08:08.216500Z

I 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}
  )

2021-01-30T21:09:20.217100Z

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

2021-01-30T21:09:46.217300Z

Given I've never used lein-git-down, I am probably not configuring it correctly.

2021-01-30T21:24:12.217900Z

A jar existing doesn't mean anything

2021-01-30T21:25:15.219500Z

A jar is just a zip file, and can contain java source code just as easily as compiled class files

2021-01-30T21:26:36.222700Z

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.

2021-01-30T21:26:50.223100Z

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

2021-01-30T21:28:40.226200Z

Which won't work if the project needs a "build" step like compiling java source to classfiles

2021-01-30T21:30:52.227200Z

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.

2021-01-30T21:33:12.228200Z

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

Jamie Rumbelow 2021-01-30T21:35:24.229300Z

Strange - looks like you’ve configured it the same as I have

2021-01-30T21:36:00.230200Z

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

Jamie Rumbelow 2021-01-30T21:36:09.230400Z

This is really useful, thanks all

2021-01-30T21:36:46.231300Z

They may only handle build steps with maven in projects that use the clojure maven plugin

Jamie Rumbelow 2021-01-30T21:37:37.232100Z

Okay – I’ve unzipped the jar and you’re correct, it’s just a handful of source files, nothing compiled

Jamie Rumbelow 2021-01-30T21:38:59.233400Z

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?

2021-01-30T21:39:00.233500Z

It is possible that library only distributes Java source files, and not pre-compiled JAR files.

Jamie Rumbelow 2021-01-30T21:39:18.233900Z

Yep, I think that’s exactly what’s happened

Jamie Rumbelow 2021-01-30T21:39:59.235300Z

I didn’t realise jars were (potentially) uncompiled!

2021-01-30T21:40:11.235600Z

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.

2021-01-30T21:41:03.236700Z

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.

Jamie Rumbelow 2021-01-30T21:43:12.238500Z

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

alexmiller 2021-01-30T21:47:56.239500Z

It’s very unusual not to distribute Java libs as compiled jars in Maven repos

dharrigan 2021-01-30T21:55:29.241400Z

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

dharrigan 2021-01-30T21:55:32.241600Z

(def foo {:a 1 :b 2 :c 3})

(condp not nil? foo
      a (branch-1 a)
      b (branch-2 b)
      c (branch-3 c))

dharrigan 2021-01-30T21:55:48.242Z

natch, that's bad code, but is there an idomatic way of doing that in Clojure?

seancorfield 2021-01-30T22:00:11.242800Z

@dharrigan Given that hash maps are inherently unordered, you'd have to provide an ordered list of keys to check, no?

seancorfield 2021-01-30T22:01:00.243500Z

(although, in this case you also have an inherent order of functions to call on specific keys' values)

2021-01-30T22:01:11.243600Z

Yes, this library does not have any pre-compiled JARs on Maven Central according to search at Maven Central: https://search.maven.org/

2021-01-30T22:01:13.243900Z

That is unusual.

2021-01-30T22:02:36.244100Z

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.

dharrigan 2021-01-30T22:03:43.244500Z

You're absolutely right! I keep forgetting they are unordered!

dharrigan 2021-01-30T22:03:56.244800Z

d'oh

dharrigan 2021-01-30T22:05:43.245700Z

I can do something like this

dharrigan 2021-01-30T22:05:47.246Z

(def foo {:a nil :b 2 :c 3})

(when-let [{:keys [a b c]} foo]
  (cond
    a "x"
    b "y"
    c "z"))

seancorfield 2021-01-30T22:05:51.246200Z

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...

dharrigan 2021-01-30T22:07:56.246500Z

(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"

dharrigan 2021-01-30T22:08:00.246700Z

that seems to work nicely! 🙂

seancorfield 2021-01-30T22:11:53.249Z

(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.

dharrigan 2021-01-30T22:12:09.249200Z

oooh

dharrigan 2021-01-30T22:12:46.249400Z

I like that too

dharrigan 2021-01-30T22:13:00.249800Z

going to save that in my "Sean's Snippets" folder... 🙂

seancorfield 2021-01-30T22:15:55.251100Z

I guess another option is first of for: (first (for [k [:a :b :c] :let [v (k foo)] :when v] ((k foo-fn) v)))

dharrigan 2021-01-30T22:21:25.251900Z

🙂 Another useful one. Thank you Sean. For me bedtime!

dharrigan 2021-01-30T22:21:30.252100Z

ttfn!