Fork me on GitHub

I’ve been playing with turning manually managed resource pools into pools that are managed by the jvm garbage collector instead. I can’t say I really recommend its use since it’s probably more trouble + caveats than it’s worth, but some of you might find it interesting nonetheless:

👀 4

Quick question. What is the reason behind partial not playing well with Java methods? Can’t it determine the instance or type at call time?


IIRC Java methods are not valid values by themselves. You cannot pass a Java method anywhere - not just to partial. You always have to wrap it.


@U2FRKM4TW - indeed. My guess is because it can’t determine the type and instance at call time, it will have to know that at compile time itself…


It doesn't have to do anything with instances or types. You can add type hints - it won't help. The issue is that the methods are not values - you cannot pass e.g. Object/toString anywhere even in Java.


Ok. Thank you.

👍 4

There's likely a more in-depth explanation that delves into JVM and describes why Java methods are not first-class citizens. But I couldn't find anything quickly.


With the functional features added in Java 8 you can pass methods under some conditions. As mentioned a little earlier (I think yesterday) in the slack channel, Clojure doesn't yet take advantage of these Java features.

👍 4

@UBRMX7MT7 I didn't know about it, thanks! My experience with Java ended on 7. :) Looking at the bytecode of an example of such method passing, it seems that it's just a syntactic sugar (that still creates a bit different bytecode) for wrapping a call of that method in a specific method in the target functional interface. With this in mind, craftybones can be correct because if we use something like obj::fn in Clojure, the compiler won't know the desired functional interface there in the general case. But I'm not very fluent in bytecode so I may be wrong on all accounts here. It would be interesting to hear from someone that knows this stuff in and out.


You know, there’s a Brian Goetz talk, maybe at the Clojure Conj where he talks about this exact problem of method signatures for lambdas


There's memfn but you might as well just use #(...) for an anonymous function based on a class method.


Anonymous functions are more idiomatic than partial anyway.


But is there a reason why a Java method can’t be passed?


Because it is not an object -- you have to have a wrapper for it


So eventually, it comes down to the fact that there is no way for Clojure to know what instance that a method belongs to right?


Java methods simply aren't first class. They don't exist as reified things you can pass around.


Cool. Thanks.

Alex Miller (Clojure team)23:12:29

Well they do exist as method handles in modern Java and perhaps the design would be different if it started now.

👍 4

In this code in clojure.test there is a try/catch around var-get: but why is that? I tried this in the REPL:

(some? (var-get (declare x)))
and it returns true, without exception


it used to throw before 1.3


Is there a recommended setup for a full stack Clojure project?


Maybe a lein plugin of some sort…?


I don't think there is a single setup that 90% of Clojure full stack developers will recommend. They tend to vary more than that. Luminus is one curated set of Clojure libraries that can be used to build the server side code of a web server project -- I don't recall if it contains anything regarding Clojurescript, though:

👍 8

I like it because in the end it's a sophisticated template (AFAICT), not a framework


I don’t mind putting together something myself, just wondering if there is a recommended path that’s all, but I will try all of the options mentioned above


Can’t recommend shadow-cljs enough for the clojurescript side


I think ring will anyway be what I use on the server side. I will try shadow-cljs on the clojurescript side anyway


@dpsutton Would you recommend it over fig-wheel?


I'm going to start looking into clojurescript this week, but so far the mist of the chit-chat I've seen is about fig-wheel


both are awesome and have solid work behind. Very likely either choice would be a pleasure to work with today. With that said, figwheel development has become a bit more occasional, whereas the commit stream in shadow-cljs has remained constant (you can always check github yourself and draw your own conclusions!)

👍 4

The little downside with shadow-cljs is that it's going its own way; don't expect any support/design from Cognitect.


Coming fron Java (and loving the little I've done with Clojure), this is a problem you don't get see as much there. That is, it's more of a gamble when choosing between libs/frameworks in the Clojure world.


Is it more of a gamble? In what way? I think there are trade-offs to be sure, but in my experience the common Clojure libs are more mature and don't need as much maintenance.


In the way that there is a smaller pool of maintainers overall compared to Java. This isn't a problem in a small ecosystem if the competing libraries are kept to a minimum though.


But at the same time you want of course more libraries competing to expand the ecosystem.


I think that has more impact on the viability of frameworks in Clojure than on libraries. There are a lot of small, composable, very solid libraries in the web space in Clojure and folks are more likely to continue maintaining something small (and well-used) than something large/complex (and not so well-used).

👍 8

Luminus is "mostly" a template that starts you off with a collection of libraries but I encourage folks to start with the basic libraries to get a feel for how Clojure(Script) handles this stuff at the base layer, before going off into the weeds with framework-like things. YMMV.

✔️ 4

I agree with that


what's the syntax again for defining multi-arity protocols...


(defprotocol foo (f [this] [this that]))


aaah, thanks


but for implementing it's (deftype t [] foo (f [this] ..) (f [this that] ..))


unless you extend{-type,-protocol}, then it's (f ([this] ..) ([this that] ..))


It seems that inside a deftype , one can implement a method "under" an interface that does not contain that method directly, but only indirectly via extending other interfaces, too?


i.e. there is no restriction that the method be "directly" in that interface.