Hi! I'm trying to get quil to work on MacOS, M1 chip (arm architecture). But opengl has been deprecated and I can't get JOGL to work at all, there don't seem to be binaries for this architecture (I guess?). Same goes for any other 3D rendering that uses opengl. Is there a way to reproducibly get it to work on this architecture, or (alternatively) to use Quil 3D rendering with Vulkan or other renderer?
I just tried on M2 with the default Quil Lein template - it worked right away.
Oh, wait, it's not 3D, duh.
Perhaps try specifying the right libraries manually? https://github.com/quil/quil/issues/387
When I got Quil working again I made the choice to move the project to use deps.edn because it made dealing with some upstream libs easier. The new version of processing has better packaging, so I’m hoping to loop back and further improve the situation
No, it doesn't change anything. Even running that specific example from that specific repo with that specific deps change doesn't do anything
Bummer. I'd try on my end but my mac pisses me off every time I have to use it, for all sorts of random BS reasons, and this morning I have already spent my weekly allowance of mac BS tolerance. :D
Huh, actually! It works if I change the deps versions to 2.4.0, and even then only with clojure-cli (using deps.edn), but NOT with leiningen. Even with the same repo and same dependencies. What could be the reason?
I'm assuming they manage deps differently somehow?
Give me 10 minutes, and I'll upload the repo
Yes, the dependency resolution approaches are different.
What is different?
You can inspect the full dependency trees and compare the actual versions. I don't remember every detail about the algorithms. I haven't used Lein in any reasonable capacity in many years, I only remember that the order of the dependencies there matters a lot, that I always had to have some manually specified exclusions in reasonably large projects, and that in general I was never a fan of the overall approach.
Oh damn, the ORDER MATTERS?!
This is insane
Thanks for cluing me in
Ah, right - when there are multiple versions of the same transitive dependency, Leiningen and Maven both pick up the first discovered. But clj picks up the highest version, making the order irrelevant.
Thank you
Hello. I am still very much a beginner to Clojure but getting good enough that I want to start using it in an existing Java application (an API service). It is painful to look at working with (say) JSON in Java when I know how much simpler it would be with Clojure. I didn't see a guide on http://clojure.org about this. I see there is some documentation on the Clojure Java API but I searched on this question within this Slack and found some comments about an old API so want to make sure I'm starting in the correct manner. Is adding Clojure to existing Java applications commonly done, or not recommended?
here is a minimal clojure / java program I wrote to run a clojure program as a service via jsvc: https://github.com/noisesmith/clj-jsvc-adapter I think it's a straightforward example of running clojure from java
Hi. The public Java API is documented here: https://clojure.github.io/clojure/javadoc/
Thanks, I saw that. My questions are it advisable for me to do this, do lots of people use Clojure this way, etc?
I have a memory that people add clojure into tests as a way to introduce the language to a project without having to have a ton of buy in. Expressivity in tests is a gateway for clojure to help out
I’ve done it several times, totally feasible to write a component or subsystem that way
But then you’ll want the whole system to be in Clojure :)
At work, this is how we approached adding Clojure to the mix. Our primary, pre-Clojure language was CFML (ColdFusion), so I built a thin wrapper around the Clojure Java API to make it a bit more "automatic". We introduced Clojure for some low-level stuff at first, and slowly migrated our entire dating platform from CFML to Clojure over several years. For us, it was a big win in several areas, but getting away from mutability and making it easier to use concurrency, and the interactivity of the REPL were the main ones at first. Over time, the simplicity of the code has made maintenance/enhancement a lot easier.
When we started out with that, it was with Clojure 1.3 (alpha) and Leiningen, so it used the old API. When Clojure 1.6 came out, we switched to the new API (and our wrapper library still supports both, to this day). We still have one small CFML app in production where the VC part is CFML and the M part is pure Clojure, but all our other CFML got replaced several years ago.
Is it advisable? I think so, but I'm very biased in favor of Clojure at this point. Do lots of people use Clojure this way? I don't think so. Most Clojurians use plain ol' Clojure top-to-bottom (and may be more likely to use Java as the low-level library language in a mostly-Clojure system, I suspect). But when you're in Language X and want to migrate partly or completely to Clojure, it's just perfect, IMO.
@seancorfield this is great to hear. In your application, does the deployed artifact contain the ".clj" code or does your build process convert Clojure code into .class files?
I definitely see the value in being able to use the REPL, both for clojure and for interactively working with our existing classes.
Yesterday I finally figured out how to use (add-lib) to load a jar into a running REPL which is great. It seems like it designed for loading jars available on a maven site, etc. Next up will be to see how to load an arbitrary jar file on disk into the REPL. I see that there is a cemerick.pomegranate that does this but wanted to see if it will also work with the "standard" clj tools.
I have been meaning to learn Clojure for years but earlier this year I finally did so and glad I did. I would say that learning Clojure has made me a better Java programmer as well.
You should be able to use add-lib just as well, but the coordinate will be {:local/root "path/to/the/lib.jar"} instead of {:mvn/version "..."}.
ha great thinking
❯ clj
Clojure 1.12.1
user=> (add-lib 'medley/medley {:local/root "/Users/dan/.m2/repository/medley/medley/1.4.0/medley-1.4.0.jar"})
[medley/medley]
user=> (require 'medley.core)
nil
user=> (dir medley.core)
abs
assoc-some
boolean?
...> In your application, does the deployed artifact contain the ".clj" code or does your build process convert Clojure code into .class files?
@doug Our deployed artifact always contains the source .clj files -- but may or may not also contain the AOT'd .class files. For the most part tho', we only AOT Clojure as the final step in a Clojure-only "uberjar" for deployment.
CFML is generally deployed as source too -- and compiles on-demand into .class files (in memory or on disk, depending on your settings). Not a lot of people know, but CFML has been a dynamic scripting language for the JVM since 2001 -- previously it was an interpreter, written in C++ as I recall. It had closures before Java and allows for quite a bit of metaprogramming, including constructing "objects" from hash maps by adding "methods" at runtime 🙂
If we'd been using a pre-compiled language (like Java, Scala, etc), I suspect we'd have built our Clojure code into source-based library JAR files for deployment. We'd have only used AOT if startup time was an issue (which it is for a couple of our "larger" pure Clojure apps).
https://clojurians.slack.com/archives/C03RZGPG3/p1719090196437099?thread_ts=1719090196.437099&cid=C03RZGPG3 Perhaps interesting to you Doug
thanks everyone, this is all great information
Ya it's quite easy. You'll want to keep it uni-directional, so only have Java calling Clojure, so that the build order can make sense. Don't have each other use each other.
Personally I would create a separate Clojure API project and start building new API end points and/or migrate existing end points as required. This is an approach covered in Domain Driven design. It keeps each project much simpler and any integration could be kept at the API level.
Then just get familiar with the Clojure Java API https://clojure.github.io/clojure/javadoc/ this lets you call Clojure from Java.
If you AOT compile the Clojure, you have to make sure it's done first, so that Java has access to the compiled Clojure classes by the time it gets compiled.
I don't recommend trying to use defclass and definterface. Just use the Clojure Java API and make your own shims in Java that use it. Then you don't even need to AOT compile the Clojure.
https://github.com/steffan-westcott/clj-otel/blob/master/clj-otel-adapter-log4j/java/steffan_westcott/clj_otel/adapter/log4j/CljOtelAppender.java is something I wrote very recently that uses the Clojure Java API. I needed to extend a Java class in a logging framework and implement a Java service. This also needs to work without AOT, since it's for a Clojure library I maintain. The Clojure Java API is small and stable, which makes all of this possible.
We should have an "Insurgency patterns" section in the docs, where strategies on how to slowly sneek clojure into stacks in different languages are explained 😄