Equivalent of java's 'method reference' syntax?

Hi,

I’m wondering if/how there is a better way to write Clojure, where in the equivalent java code you’d have a method reference.

Take java.time.DatetimeFormatter’s parse method for example. In java you could write:

formatter.parse(text, LocalDate::from)

The second arg is declared to be a TemporalQuery, a SAM in the java jargon, so you can just pass a method reference of a java method that has the same signature as the one method in TemporalQuery.

The following, equivalent code works in Clojure, but is there a neater way to write it?

(.parse formatter text 
(reify TemporalQuery
      (queryFrom [_ x] (LocalDate/from x))))

Would memfn do the trick?

(.parse formatter text (memfn LocalDate/from))
;; Untested!

thanks but no, that wouldn’t work. Still, I’ve never noticed memfn before so thanks for pointing it out!

What I guess is missing is the (.-from LocalDate) property syntax that Clojurescript has.

Afaik Clojure 1.10 was the first to require Java 8 or higher, which was when these method references were introduced, so it makes sense there’s no direct equivalent (yet, afaik?)

Clojure has the field assessor syntax:

(.-instanceField instance)

But Java methods are not fields. Java methods aren’t first class like that.

It is my understanding that method references are java compiler syntax sugar. The Clojure compiper currently doesn’t have that same sugar, it would need to perform some type inference and all for that, because it has to figure out what functional interface it needs to reify, since they are all different.

So right now your best bet is just a wrapper function/macro for each TemporalInterface you need to use that just does the reify you have.

But I wonder if something more generic could be made using the metafactory https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html

Thanks. I’ll take a look at that

Just want to let you know that I went down searching for a way to do this last month, too, and ultimately landed on reify as well. In fact, it was the same class I was referencing. Am interested in seeing if there’s a nicer solution but I think the reify one looks fine enough on its own.

The cleanest way to do this is not to use LocalDate::from at all, but to call LocalDate/parse directly and pass the DateTimeFormatter as an argument:

(java.time.LocalDate/parse
  "2016-11-08T18:24:25Z"
  java.time.format.DateTimeFormatter/ISO_DATE_TIME)
;=> #object[java.time.LocalDate 0x16cddb1f "2016-11-08"]

(I found this searching for the best way to use java.time.format.DateTimeFormatter from Clojure, so I decided to record the solution here. It doesn’t answer the question as it was asked, but it will be useful for other searchers.)

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.