Fork me on GitHub

As someone coming from Ruby/JS, what Java concepts that are important/good to know to be an effective Clojure developer?


Was a number of great answers below. I would add AOT compilation and (:gen-class) for the entry point of the program. defrecords create mini Java classes. That is why they are initiated with a . in front of the record name (eg,

(defrecord MyRecord [first-arg second-arg])

;; create an instance of MyRecord
(MyRecord. :arg1 :arg2)
), and clojure automatically creates a helper function for you which is
(map->MyRecord {:first-arg :arg1 :second-arg :arg2})
) All the args specified are created inside the class, and the record then acts map-like after that with any additional keys behaving like a normal map in performance (IIRC).


I'd say the classpath and namespaces.

Joshua Suskalo13:09:15

the classpath is just the way that java loads code and resources into the running system. The classpath is a list of places where it will find code and resources that sets the initial state of class loaders, when then at runtime can change if you fiddle with it.

Joshua Suskalo13:09:38

But yes, it's good to look into how it works at a basic level, but I wouldn't say critical if you're just starting out. It's very important to know about though.

Joshua Suskalo13:09:48

Namespaces I think are more important for beginners to learn about than the classpath.

👍 2

Another example of this is just the $PATH from your shell

Joshua Suskalo13:09:07

biggest difference is that PATH doesn't change during your program's runtime. usually the classpath doesn't either, but it can.


well, the PATH can too in some programming environments, but not in the JVM

Joshua Suskalo13:09:25

good to know, I wasn't aware of that


the classpath cannot change during runtime


classloaders can choose to ignore it and load from elsewhere

Joshua Suskalo13:09:40

not the classpath itself, but the classloaders can change the same thing that the classpath sets the initial state for.

Joshua Suskalo13:09:44

That's what I meant.


In babashka the classpath (own implementation, != java classpath) can change during the lifetime of a script using babashka.classpath/add-classpath or babashka.deps/add-deps

👀 2

it's more a source path than a classpath, but similar idea


Question: I am relatively new to the JVM per se but — why do I need to make sure that the path of my files has to follow my namespace as well? For instance, (ns app.core) requires me to have src/app/core.clj. Is there an historical reason? Can I change that somehow and inform the JVM that I want to randomly put files everywhere (which is what .NET is doing for instance)? Not saying it’s a good idea, just trying to understand if it’s a possibility.


@vincenz.chianese not possible, namespace names have to follow the dir structure if you are using them in a project


note that you have to replace foo-bar in the filename with foo_bar in the directory structure


Technically, there is a way with in-ns, but you shouldn't do that.


There are ways using load, load-file, in-ns etc, but this isn't typical


Clojure is more dynamic than ClojureScript where the above isn't support at all


Oh whoa. That’s kinda disappointing, I thought there would be a way. My idea was that namespaces are indeed used to decouple the directory/project structure from the logical way you import stuff, so that even in case you move files everything still works (which is the case in .NET). If they have to match, I do not see the point of having to declare them anyway. They could be implicitly calculated. Again I’m not saying it’s a good idea, just thinking aloud here

Joshua Suskalo14:09:03

The reason for this by the way isn't anything inherent to the JVM, it's that Clojure's implementation of code loading with require uses the namespace name to identify the file names to look for on the classpath. You could use load to manually name the files and load them and in that case the name of the namespaces don't need to correspond to the paths, but then you have to be concerned about load ordering and you can't rely on Clojure auto-discovering the code files to load for a given namespace.

Joshua Suskalo14:09:31

The JVM itself requires that paths correspond to packages, but there's nothing about that which means that compiled artifacts from arbitrary languages targeting the JVM must follow this pattern, and the JVM itself provides tools for scanning the classpath to find classes, which means languages could be implemented to load all code from the classpath for the language, also assisting with this "problem".

Joshua Suskalo14:09:40

Or I guess more accurately, just allowing for another design.

Joshua Suskalo14:09:31

for the sake of the channel, in this thread I mention how it's not necessarily the JVM's fault that code in the source language matches file paths, and that clojure's implementation of require is what causes this behavior in Clojure.

💯 2

Ok so this is contradicting what we were saying before. This is a Clojure behavior, right? @suskeyhose

Joshua Suskalo14:09:29

Yes, and like Alex said, namespaces don't correspond to files once they're loaded. The only reason a namespace name matches a file path is for loading with require


Ok cool. Thanks for the clarification


so in general I would stick to the normal way of doing things


Hold on — this is a JVM limitation though right? It’s not Clojure, it’s just the way the JVM works


it's a limitation of require , and normal sane clojure code uses require


looks like this was mentioned in another thread


it very much relates to the classpath, if you want to load namespace then Clojure knows where to find it on the classpath using these rules


first foo/bar__init.class, then, foo/bar.clj, then foo/bar.cljc etc


I still fail to understand who’s dictating this rule. Is it Clojure or the JVM?


this is from the JVM, but it's been adopted by ClojureScript too, babashka also has this rule, in general I think it's a good idea


So no matter if I do Java, Kotlin Clojure, I cannot change this behavior; correct?


Clojure could potentially work around that, but it would require either some explicit mapping mechanism or loading all CLJ files, which we don't want to do.


Also tooling like clj-kondo etc won't work correctly if you are trying to go against the current


Yes folks do not worry, I am not trying to revert the order of the things; I am trying to understand who’s setting up the behavior — and it seems to be the JVM

Alex Miller (Clojure team)14:09:46

it's definitely a choice of Clojure's design that namespaced names map to the typical hierarchical Java package structure for finding source/class based on namespace name.

Alex Miller (Clojure team)14:09:13

that said, namespaces at runtime are independent from what exists on disk. a single file can create multiple namespaces at load time. and multiple files can define functions that exist in the same namespace. 1 file :: 1 namespace is a simplifying and useful base model though.

👍 4

looks like it is java 17 release day. I use sdkman and i'm only seeing 17 images under which i don't recognize. Also, i'm pretty sure adoptopenjdk has been renamed to adoptium? But not seeing those with sdk ls java


afaik Adoptium is the project, the JVM is called Temurin now:


For me in SDKMan, and SAPMachine are the only stable entries for 17 so far


ah, i'll keep an eye on temurin. didn't know that was the name for the jvm from them. thanks


It’s really confusing, tbf


this seems to track the process for releasing 17 and targets sept 30th