This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-08
Channels
- # announcements (4)
- # aws (3)
- # babashka (5)
- # beginners (16)
- # cider (8)
- # clj-kondo (3)
- # clojars (8)
- # clojure (115)
- # clojure-uk (15)
- # clojurescript (18)
- # data-science (5)
- # datomic (14)
- # fulcro (49)
- # funcool (6)
- # graalvm (3)
- # graphql (4)
- # lumo (17)
- # malli (5)
- # off-topic (15)
- # reitit (18)
- # ring-swagger (8)
- # rum (2)
- # shadow-cljs (35)
- # tools-deps (18)
- # uncomplicate (2)
- # vrac (1)
Is there any way to do a e.g. 32 bit bitwise-and for two int
's? (bit-and (int 1) (int 3))
returns a Long, apparently. Or maybe there's a way to call a java operator via interop, or something like that?
@jason358 Can't you just cast it to int
afterward? Given JVM types are all signed...
sign is not a problem, bitwise stuff works anyway. I want to avoid the unnecessary conversion to 64 bits and back
Clojure works in Long all the time so you're going to get not only int
-> long
but long
-> Long
boxing as well unless you're very careful.
I'd recommend profiling your application, and if that part of the code becomes something that becomes noticeable in its fraction of time, then optimize it. Optimizing it in an easy-to-predict way could easily involve writing a bit of Java code.
Java methods yes. Java operators, no.
You can write a one-line method that does that, and call that. As Sean mentioned, ensuring that Clojure-compiled JVM byte code uses Java primitive int values is challenging, if it is possible.
You can run ClojureScript, which targets JavaScript.
There is GraalVM, which for some subset of Clojure programs can generate native executables. The #graalvm channel here is a good place to find out more from experts on that topic.
Any particular motivation for avoiding the JVM that you have in mind?
@tylertracey09 Clojure (and ClojureScript) are designed as "hosted languages" -- Clojure is designed to leverage the JVM, ClojureScript is designed to leverage JavaScript (browser or Node.js), ClojureCLR is designed to leverage the .NET system...
It's just been years since I did anything JVM related and the java codebases I worked on towards the beginning of my career were really bad. So personal horror stories combined with a lack of familiarity
The JVM has improved a lot over the last 23 years that I've been using it 🙂
There is good Java code/libraries out there, too, and likely in most cases you can avoid looking at Java code while developing with Clojure.
Ah so does that mean Clojurescript is semantically equivalent to clojure? I would imagine there have to be some differences due to concurrency stuff
Plenty of Clojure devs rarely look at Java code. They more often look at Java API documentation
ClojureScript is single-threaded, of course.
An overview of main differences can be found here: https://clojurescript.org/about/differences
There are many differences, and there is no language standard for either, so comparing them becomes very tricky
Depending on what you want to do with Clojure* there may be tools that provide Clojure-like programming in certain situations... babashka for shell scripting, sci for a "Small Clojure Interpreter", and several others...
For now my goal is pretty simple: wrap my head around designing systems using functional composition. I'm still pretty early on in the "conscious incompetence" phase of things
(there are a lot fewer differences between Clojure and ClojureScript these days than there used to be, but there are still important differences -- and in my opinion the Clojure/JVM stack is way, way simpler to work with than the ClojureScript stack)
I'm pretty set on Clojure but, out of curiosity, what other functional languages do you folks recommend?
If you want to run code that runs in a web browser, definitely go for ClojureScript of course. If you want to run code on a server, I would recommend imagining that the worst Java code you have seen died a slow death (maybe with a few holdouts that you can avoid), and try Clojure/Java.
I have only done very brief experiments in Haskell, and it has a much different emphasis than Clojure with its type system. I can't recommend for or against it given my limited experience, but definitely worth taking a look at for at least a little while to get a flavor of it.
@tylertracey09 Are you just looking to learn, or do you have a project in mind? Also, what platform/language(s) do you normally develop on/in?
The one thing I really miss with clojure is simple c interop, it is the first thing I notice using any non-jvm language, even Haskell's is pretty good
it seems like there is some recent work in this direction in java land with javacpp and panama. does any of that look promising?
The most most promising stuff I've seen is some libraries the jruby guys have. jnr I think it is called. But I still found it to be pretty high friction it terms of figuring out dependencies to make it work. I'll evaluate Panama when it lands in a jvm
I'm planning to build a platform to help musicians connect locally (since, as a musician, I see a huge gap there). I was hoping to use clojure to develop the backend of that system. I typically find myself in the JavaScript ecosystem these days. I was an early NodeJS adopter in like 2011 and I've been kind of stuck there ever since. Not that its a bad thing
I only have second-hand knowledge of JavaScript, from what I have read from others, with the impression that it is huge and thriving, and perhaps a bit chaotic and/or prone to fads in libraries/tools because it is huge and thriving. Clojure/Java tends to emphasize stability in APIs and backwards compatibility much more. You know much more about the JavaScript world, though, so take my words with the hunk of salt the source deserves.
Regarding the stability of APIs of Clojure, it is fairly common for people new to Clojure to look at a library on Github, see it has had a handful of commits in the last 2-3 years, and presume it is dead/non-functional. It might be, but it is just as likely that it is working as designed, and hasn't needed to be modified to continue working.
@tylertracey09 If you want to use ClojurScript and Node for your backend, https://macchiato-framework.github.io might be a good option to explore. There’s a #macchiato channel here as well if you want to learn more.
There have been various templates and sample applications published, but most I recall seeing were web server back end applications, sometimes with ClojureScript interactive front ends. If there were sample desktop applications published, there were definitely fewer of those (probably not 0).
At least as far as major libraries to consider, there is JavaFX GUI lib for Clojure/Java, and things like Electron with JavaScript that ClojureScript might work with.
A Google search for the terms clojure javafx turns up a Clojure wrapper library for javafx -- I did not notice if it had much example application code it referenced or included. Also a few web forum discussion about it, which would be good discussions to read through to see if anyone asked about, and or linked to, open source apps as examples.
There is also a Clojure/Java library called Swing that wraps a different Java GUI library, other than JavaFX.
is there a convention to name the accompanying function for a macro? like the function that actually does the code manipulation work for the macro
looks like the convention is *
, so like for the macro foobar
the function is foobar*
. thanks!
That is one convention but there are even others used in core itself and certainly others used elsewhere, so don’t feel bound by that
The * functions are actually even more special in that they are the gateways into compiler special forms
It matters a lot whether you expect people to actively use both too. If so, I usually work harder at good names for both (like def (macro) and register (function) in spec 2)
I see, thanks @U064X3EF3!
Guys, I am having an issue. I have an edn file where one of the properties is the fullpath to a function somewhere in the classpath
when I use aot inside the repl itself, everything works fine, and I can resolve the symbol and execute the function
but, if i create an uberjar, even though i am using aot in the uberjar profile, the resolved symbol is always null
any ideas on why this is?
you are right, I figured it out, I add to require the namespace from the symbol, and then everything started working as expected 🙂
In Lein's mixed projects doc, authors said:
Having one source root contain another (e.g. src and src/java) can cause obscure problems.
What are these problems?
Just a wild guess - if both src
and src/java
are indeed registered as source roots, you could end up with errors like "ns a.b
has wrong path java/a/b.clj
".
I've seen weirdness in editors from stuff like this
FWIW, the author of shadow-cljs advocates against such splitting: https://shadow-cljs.github.io/docs/UsersGuide.html#_source_paths "It is not recommended to separate source files by extension (eg. src/clj, src/cljs, src/cljc). For some reason this is widely used in CLJS project templates but it just makes things harder to use."
And I tend to agree with him. It's a bit more pleasant to work with sources that are not split by file extension.
how would i separate java packages from clojure, and where to define a line between backend and frontend
A middle ground seems to be src
for , java
for Java. Both at the project root.
A bit asymmetrical, but also enjoyable?
> how would i separate java packages from clojure Why? I've used Java before, and IIRC I didn't have to separate anything. > where to define a line between backend and frontend Again, why? What purpose would such separation serve?
If the Java code is intended to be called from Clojure, why not make it a separate project, build it as a Java project, and then just depend on it from Clojure.
But then I'm using CLI/`deps.edn` so don't expect to compile Java as part of a Clojure project 🙂
CLJ can have functionality that's used by both Clojure and ClojureScript (via macros), CLJC - same deal, only more that just macros could be used in CLJS. Java can be used by said macros. Everything is intertwined. Separation by file extension is no less arbitrary than separation by the number of lines in source files. Yes, the processing of said files is different. But it doesn't matter.
If you have to keep such separation in mind at all times, that's just extra cognitive load. An anecdote - I even store Python source files and ANTLR4 grammar definitions with the rest of the Clojure[Script] code. Works perfectly. And I don't have to think each time, what is located where.
@U2FRKM4TW, if you're putting .java and .clj in one source tree, does that mean you're not using deps.edn (based on the comment from @U04V70XH6)?
@UBRMX7MT7 No, it doesn't mean that. I'm gonna guess here and say that Sean meant that there are Lein/Boot plugins that compile Java for you, and that deps.edn
doesn't have anything like it.
That's true, but that doesn't prevent you from using Java in a deps.edn
-based project. You can have a separate build step, you could integrate compilation into your app workflow manually, you could use https://github.com/ztellman/virgil. After all, that's more or less exactly what those Lein/Boot plugins do.
If you had to start with a Luminus generated app but then make a few changes to make it better fit your preference, what would they be? Are there any deficiences or design decisions that fall outside the norm of best practices?
My biggest issues with Luminus as a beginner (this is a few years ago now) was that it was too complex for me to understand, and there was no easy way for me to integrate fixes that were in the original Luminus template I used.
As far as different design decisions, the things that aren’t covered by the different profiles that I would want to use are integrant (instead of mount) and deps.edn (instead of leiningen or boot) - most everything that I would want to use can be brought in as an extra profile.
As far as the bugs I ran into, I wanted all the bells and whistles right from the start and put a whole bunch of profiles in. There weren’t any direct conflicts but I think I was one of the first to try a particular combination and ran into some bugs. It’s been used by way more people by now and should be a lot more solid, but I would still err on the side of simplicity if you are just getting started.
I agree with Shaun here: Luminus is very complex for beginners -- when something goes wrong, which it usually does as they try to make changes.
If you’re looking for something to really understand the thought behind Luminus, https://pragprog.com/book/dswdcloj3/web-development-with-clojure-third-edition is written by the Luminus developer - reading the first and second editions of his book helped me a lot to understand where the design decisions came from.
Even the minimal template is pretty substantial.
Yeah, and when it goes wrong you have to start to learn how leiningen works in a lot more detail than should be expected of any beginner to Clojure.
I have nine years of production Clojure under my belt and I still think Luminus is "too much". It feels like Rails to me, and I never liked that, for much the same reasons.
(someone should really make you a Clojure cake for your 10th anniversary)
If you have some specifics of what kind of app you are trying to build, I bet you could get some good advice on where people would start. Biggest things in my mind is to try to keep it as simple as possible, make sure you have something that work well for configuration and keeping your passwords out of version control, and gear everything towards a good REPL workflow. There are different options for all of those and you will likely find something you really like after trying a few of them.
@U061KMSM7 Back to the original question: I'd want the template to use deps.edn
instead and to not include anything not needed for the minimal web app to start up -- and have all the rest be optional.
(that means no Docker, no Procfile, no Capstanfile etc -- there's a lot of "noise" even in the minimal template project)
Well, I’m going to be handling a one-man contract, and in the past when I would ‘start from scratch’ I often found myself scrambling to add a library for some functionality I didn’t think I needed, figure out how to use it, then integrate it. Hopefully I’ve learned my lesson and won’t repeat that mistake.
Yes, I’d get rid of those extra files, and probably go with a straight clj
based deployment. Maybe with capistrano? No Docker for me!
You'd still have to learn how all the libraries in the Luminus template work.
I’m not sure that using Luminus would actually solve that problem - it’s a lot harder to add new dependencies after that fact, so unless you pick the right profiles at the start you will still have an issue.
The base template has 25 libraries in the :dependencies
vector 👀
And it's strange that the docs say Reitit is optional and it is added when you say +reitit
but that is already listed in the dependencies.
Where I would use Luminus is if I knew what I needed, and when the documentation guided me to the same place I was looking to go (similar to the times when Rails and other large frameworks are great - when you’re trying to do what the template developers expected, you are probably going to have a smooth path to get there).
Yes, +reitit
became standard, I saw the same thing. 🙂
As far as other changes, I would also never start with reitit as my first routing library - it is super complex and you have to understand way, way more than is necessary to do simple routing. Works great once you figure it out though 🙂
My base for a SSR (server-side rendered HTML) app would be Component, Selmer, Compojure, next.jdbc... I don't do cljs so I don't know what I'd want for that. Pretty sure I'd look at Shadow-cljs first. Reagent. Not sure what else.
I had one medium sized Luminus project that worked well, but that was a couple of years ago. So I need to refresh my memory and catch up on some new tech.
This project will be +reitit +postgres +re-frame +shadow-cljs +auth +site
In-house app. I’d use RoR except I don’t want to. 🙂
I’ve not tried Component yet, vs Mount.
I settled on Integrant with Aero, it is a nice combination when you get it working
Hmm, I’ll add them to my tech radar…
@U054BUGT4 psst, if you tried Edge and loved /hated it, I'd love some feedback (it's an integrant / aero starting point)
@U09LZR36F I haven't tried Edge, but I did look at it when it was first released and I think it was one of the reasons I took a look at aero.