This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-14
Channels
- # announcements (40)
- # aws (9)
- # babashka (21)
- # beginners (75)
- # calva (56)
- # chlorine-clover (1)
- # cider (12)
- # circleci (1)
- # clj-kondo (7)
- # cljsrn (13)
- # clojars (3)
- # clojure (171)
- # clojure-dev (11)
- # clojure-europe (64)
- # clojure-nl (11)
- # clojure-spec (6)
- # clojure-uk (9)
- # clojurescript (31)
- # conjure (1)
- # cursive (7)
- # datascript (7)
- # datomic (9)
- # emacs (4)
- # fulcro (65)
- # introduce-yourself (1)
- # jobs-discuss (7)
- # kaocha (7)
- # lsp (39)
- # missionary (5)
- # off-topic (54)
- # pathom (10)
- # re-frame (6)
- # shadow-cljs (110)
- # tools-deps (41)
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 see, do you mean this? https://docs.oracle.com/javase/tutorial/essential/environment/paths.html
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.
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.
Namespaces I think are more important for beginners to learn about than the classpath.
biggest difference is that PATH
doesn't change during your program's runtime. usually the classpath doesn't either, but it can.
good to know, I wasn't aware of that
not the classpath itself, but the classloaders can change the same thing that the classpath sets the initial state for.
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
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
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
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.
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".
Or I guess more accurately, just allowing for another design.
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.
Ok so this is contradicting what we were saying before. This is a Clojure behavior, right? @suskeyhose
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
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 foo.bar
then Clojure knows where to find it on the classpath using these rules
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
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
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.
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.
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.
Ok so this is contradicting what we were saying before. This is a Clojure behavior, right? @suskeyhose
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: https://adoptium.net
For me in SDKMan, http://java.net 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