Fork me on GitHub
#clojure
<
2024-03-08
>
jf02:03:27

hi all, newbie qn here. If there is a more appropriate channel for this, pls let me know (I don't see any right now). I'm hoping to be able to introduce Clojure to an existing Java codebase... but it will definitely take some time. I was thinking to maybe start out with using Clojure to do tests (it's a web app). Is something like this possible, where the code is in Java... but I can utilize Clojure to do testing?

Heather03:03:26

If you’re doing browser/selenium testing, you could definitely write all that in Clojure since it would be a totally different app for those tests. It’s probably possible to use Clojure to do testing of Java functions, but I’ve not seen it done.

dpsutton03:03:51

Source in Java. Tests in clojure. Could be a good example for you

gratitude-thank-you 1
Alex Miller (Clojure team)04:03:37

I hear people suggest this a lot but tbh it has never made sense to me. I think you’re better off defining the interfaces for a component in Java and just implementing that component in Clojure.

👌 2
practicalli-johnny07:03:01

I suggest the easiest approach is to write the app in Clojure as a separate project, especially if the Web app is providing an API. This is also a clear way of showing the difference between Java and Clojure. There are some nice templates to help create an API web app, like https://kit-clj.github.io/ or https://practical.li/clojure/clojure-cli/projects/templates/practicalli/ The practicalli/service template creates a working APi with a few endpoints, swagger, logging, etc. Optionally with Donut or Integrant for component management

jf07:03:05

thank you! there is an API alright. I might just try this approach

Ernesto Garcia08:03:50

May I suggest to add a trivial 0-arity clojure.core/distinct? that just returns true? In particular, that makes it more usable for (apply distinct? coll) , which I guess is a common use case, but currently throws an error for empty collections.

👍 2
tomd08:03:08

Sounds like a good question for ask.clojure

phronmophobic08:03:17

There's a jira ticket for this, https://clojure.atlassian.net/browse/CLJ-1179, but I couldn't find an https://ask.clojure.org/, which is usually how the community interacts with clojure development.

tomd08:03:32

Strange. Seems like a vacuous truth. Which clojure does support via every? and others.

daveliepmann08:03:54

> Rich declined it, implying that it was not a change he wanted. Not sure of the reason. [2014] 😬 Seems worth an ask, it's been 10 years

Ernesto Garcia09:03:39

Is there maybe a good alternative to (apply distinct? coll) ?

tomd09:03:31

I doubt you'll do better than

(defn my-distinct?
  ([] true)
  ([& xs] (apply distinct? xs)))

henrik09:03:43

I asked an AI whether this is trivially true: > Given the description of the distinct? function, if it is provided an empty sequence [], it should return true. This is because, in an empty sequence, there are no elements to repeat, so by definition, every element (of which there are none) is unique. Hence, the condition for distinctness is trivially satisfied. Sounds reasonable that there should be no ambiguity here.

tomd11:03:58

More generally, as clojure has fnil I wonder if the presence of an f0 hof would be useful:

(defn f0 [f x]
  (fn
    ([] x)
    ([& xs] (apply f xs))))
It means this issue could be approached like so:
(apply (f0 distinct? true) [])
;; => true
Maybe worth suggesting? :thinking_face:

Ernesto Garcia15:03:08

Except for juxt , there isn't an obvious trivial value to return for those, is there?

tord10:03:37

I am usually a happy cider user, but I am toying with the idea of temporarily using something else, for a somewhat unusual reason: I am planning to introduce Clojure at a workplace where most of the developers are likely to be somewhat skeptical to Clojure, and I think they'll be even more likely to reject the idea if they see me using Emacs. I guess the two most obvious candidate replacements for cider would be Calva or Cursive. How do Calva and Cursive compare these days? What are the pros and cons? I don't have the time to learn and evaluate both at the moment.

thomas10:03:30

maybe also ask in #CBE668G4R?

p-himik10:03:33

What is the current language that's used at that workplace?

tord10:03:42

They use TypeScript, Java and C++. Probably some others as well. It's a big company, and I don't know them very well yet.

p-himik10:03:58

Cursive will probably be a better bet since it has the best support for Java given that it's a plugin for IntellIJ IDEA.

thomas10:03:29

in that case I'd start with the Java side of things... they are already familiar with the JVM etc.

tord10:03:04

Yes, perhaps Cursive is the best place to start. I'm also personally somewhat more familiar with JetBrains IDEs than with VS code, which might be another practical advantage.

vemv10:03:33

Calva uses clojure-lsp and cider-nrepl, among other tech. It's all OSS Cursive is based on proprietary implementations (Cursive itself, and IntelliJ) While I don't believe in 'proprietary' being a negative, most practically, when you have a problem with Calva or the like, one has support from a wider variety of developers, and you can always take a look at the source yourself

tord10:03:46

Those are valid points, but my impression is that both alternatives are so mature and stable that few people encounter serious issues with either of them?

p-himik10:03:25

And those points are hardly selling when it comes to showcasing a new language.

vemv11:03:03

Things are always changing (see Clojure 1.12) and also it's not rare for projects to have unique intricacies https://github.com/cursive-ide/cursive/issues isn't exactly encouraging to me But yes, in the end one can pick anything - tooling is rarely the bottleneck

p-himik11:03:54

> isn't exactly encouraging to me Unfortunately, that list itself isn't maintained all that well. Of course, not saying that there are no real issues - I encounter them myself, even beside desired feature requests. But there are a lot of duplicate issues, questions, outdated issues.

pez11:03:18

As the creator of Calva, I am biased of course. Still think there’s a strong case for Cursive if people come from Java. Cursive is very strong with the Java intersection of things. Ultimately for your colleagues it will come down to which editor they are comfortable with. Calva has a Getting Started REPL, that you could spend some 15 minutes to check out, just to get an idea about what the colleagues choosing Calva will encounter.

Mario G11:03:51

They're both great. I'd probably try to understand which one between VS Code and Intellij is more popular in your audience and be driven by the result of this independent survey. I'd keep in the equation also is it smooth or a pain to get software licenses in this workplace?; if there's the risk of getting Cursive licences becoming another tedious task, I'd personally pick VS Code and move on

mmer11:03:55

Which eve one you decide on there are some key things you should let them know about - repls obviously and some key shortcuts, like send to repl, and the one I use most the Slurp and Barf.

phill12:03:19

Java is ok with VS Code! There are Java plugins from, I think, Red Hat. And I seem to remember seeing a Java LSP start up. I do not know how the VS Code Java support compares on the basis of exotic features like refactorings, but if the plan is to transition away from Java anyway, the only refactoring you really need is "Convert to Clojure", which will, I believe, be announced for Calva in the very near future, maybe April 1.

p-himik12:03:38

> Java is ok with VS Code! Can you go from e.g. (cons ...) in your code to (def ... cons ...) in the Clojure's code, and then, without interruption, directly to clojure.lang.RT.cons, then to clojure.lang.PersistentList and find usages of that specific constructor? List time I tried (albeit, more than a year ago), it was pretty much impossible without lots of interruptions like full-text search or manually entering a class name or manually navigating to a package. With IDEA, every single step in that chain is exactly one mouse click or one keyboard shortcut. Of course, different people have different workflows, but I personally find the ability to navigate the whole codebase, including the Java implementation, to be of immense help.

p-himik12:03:43

Oh, almost forgot - there's also built-in decompiler of Java classes. A fantastic tool that helps figuring out how some of your dependencies work. With all that smooth navigation built into it.

practicalli-johnny17:03:08

The choice is simple in my view. Use the editor that is already preferred amongst the developers for their current work (or is used by those most open to the idea of a new language). The capability of Clojure is largely irrelevant for early discussion. Lots of editors support Clojure sufficiently well. If the editor becomes a discussion point it's more likely the editor will become the focus of the discussion rather than the benefits of Clojure. If the developer team get hung up on the use of Emacs or use of parents, then not enough value of Clojure has been conveyed up front, or related to existing challenges they have. Or you've simple engaged with them at a bad time and they are too busy / stressed / exhausted from all the other work/deadlines. Honestly I wouldn't try and convince them all at once. I would build something that just works and is happily running in production. Or build something that solves a nasty problem that they have otherwise struggled with Or find one or two of the team that are open and you have a strong relationship with find out what will convince them to take a meaningful try. Then there are more of you to advocate Clojure. I see a lot of people fall flat trying to introduce a tool, language, etc because they haven't spent enough time considering the needs of those they are trying to advocate to. It is a significant challenge.

seancorfield20:03:01

@U2FRKM4TW VS Code/Calva/LSP has a built-in Java decompiler now. You can go from cons to clojure.core/cons easily and then go to clojure.lang.RT but it doesn't currently navigate to the cons function in that (perhaps if I had a Java extension installed, that step would be easier).

p-himik22:03:21

@U04V70XH6 Just tried. The amount of friction is still insurmountable compared to IDEA. I won't list all the issues, but with the current state of affairs I myself, regretfully, still can't use Calva for my projects. Installing the MS Java pack affects nothing.

seancorfield22:03:54

Good to know. Luckily, I don't do any Java so VS Code works great for my use cases. I've never liked IntelliJ (JetBrains kept giving me free licenses years ago, asking me to review it for them!) -- I was more of an Eclipse person (but I haven't used that for years now). I actually do have IntelliJ installed, because I've been trying to test Digma with Clojure and Digma doesn't support VS Code yet... but it feels painful every time I open it up 😞

p-himik22:03:46

Heh, my experience seems to be the exact opposite, including the Eclipse part. :) It's been a decade since the last time I tried it, but back then it used to choke on large projects (10e7 loc, GBs of deps) and it was incredibly easy for some mundane plugin to do something incorrect that would hang the whole IDE. You could hear regretful moans in the office every half an hour, which stopped the moment we switched to IDEA.

1
cfleming06:03:59

As the Cursive developer, I’d also recommend using whatever they’re familiar with. If they do a lot of Java that’s likely to be IntelliJ, if they’re doing a lot of Typescript it might be VS Code. It’s true that my issue tracker has gotten out of control, but I think Cursive is mostly a relatively problem-free experience for most users these days. If you need any help, feel free to ping me, either by DM or in #C0744GXCJ

1
metal 1
Mario G11:03:42

Definitely I'd go slow judging the quality or reliability of a product measuring an issue tracker (and I'd double check what's exactly in it). Cursive is rock solid and its user base is usually very happy with it

leifericf19:03:21

I've been doing a deep-dive into Lisp dialects on the BEAM (Erlang's VM) and made an interesting observation: During https://www.youtube.com/live/CAOrdVJTUow?si=74hRdseFqVveTB7b&t=1977 (timestamp: 32:57-35:04) about https://lfe.io, Robert Virding (co-inventor of the Erlang) gets a question about tail-call optimization in the BEAM. In his answer, he mentions an implementation of Erlang for the JVM (https://github.com/trifork/erjang), which implements tail-call optimization. It sounds like someone has managed to do tail-call recursion/optimization on the JVM. He also mentions he was surprised Clojure does not have it for that reason. I've heard in some of Rich's talks and elsewhere in the Clojure community (@ericnormand wrote about it https://ericnormand.me/article/problems-with-the-jvm) that Clojure has the loop + recur construct as a pragmatic workaround because the JVM does not support tail-call optimization. Did we miss something that Kresten Krab Thorup (the guy behind Erljang) did not? :thinking_face: I don't understand this well enough to look deeper into the actual code of Erljang, but I found it interesting that Vriding seems to believe it is possible to do tail-call optimization on the JVM as exemplified my Erljang.

p-himik20:03:21

loop + recur is not about recursion. But recur at the level of a function's body is. The technical aspects of the Erljang's implementation: https://github.com/trifork/erjang/wiki/How-Erjang-compiles-tail-recursion The linked article is 404'ed, but here's its copy in the Internet Archive: https://web.archive.org/web/20100110155216/https://www.javalimit.com/2009/12/tail-recursion-in-erjang.html

👀 1
💡 1
leifericf20:03:11

Nice find, thanks for the link!

p-himik20:03:15

A few thoughts from someone who's not involved in the development of Clojure at all: • recur is much more explicit - it fails if it's not a tail call • Vars can be changed in Clojure at run time: (defn f [x] (alter-var-root #'f (constantly inc)) (f x)) is syntactically a tail call but actually isn't • Non-self tail calls are also supported in Clojure with trampoline, which is also much more explicit than regular calls

💡 1
leifericf20:03:44

Whoa, cool—I hadn't seen trampoline yet.

hiredman20:03:49

Um actually, it still is a tail call, just no longer a self tail call

hiredman20:03:30

A tail call is a tail call, changing the target doesn't change that

Alex Miller (Clojure team)20:03:44

they've been promising us tail calls in the jvm for like 15 years, I'll believe it when I see it :)

😅 3
leifericf20:03:27

Yeah, the questioner in that talk with Vriding also mentions some professor who made a pitch to Sun, which they rejected.

Alex Miller (Clojure team)20:03:18

the main reason given was always stack based permissions checks, which was shown to be not an issue like a decade ago, and is now going away entirely

💡 1
ghadi21:03:01

it also is one of those features that a vocal minority of users want but in reality we've been fine™ without.

👍 1
ghadi21:03:55

like how every thread about Loom / Virtual Threads has someone saying "but why no full continuations?"

hiredman22:03:43

https://eighty-twenty.org/2011/10/01/oo-tail-calls "Why Object Oriented Languages Need Tail Calls" originally by guy steele when he was working on fortress back when it looked like maybe the davinci vm was going to bring tco to the jvm is very compelling

👀 1
hiredman22:03:37

tail calls on the jvm would also fix things like concat's propensity to blow the stack

hiredman22:03:26

I can understand not exposing continuations (I think it is lame, but whatever), but no tail calls does cause real measurable problems