Welcome! Please see the About page for a little more info on how this works.

+8 votes
in Clojure by
closed by

There are a lot of SAM types that are not FI in the JDK - some prominent ones are Executor, ThreadFactory, etc. Increasing the scope of what we adapt would allow us to be closer to Java’s support and would expand the scope of where this support can be used.

Simple example:

;; Adapt Thread constructor method value to ThreadFactory (not FI)
;; Use the factory to get a Thread with a Runnable and start it
(let [^java.util.concurrent.ThreadFactory tf ^[Runnable] Thread/new]
    (.newThread tf #(println "hi"))))

Execution error (ClassCastException) at user/eval145 (REPL:1).

class user$eval145$invoke__Thread_new__149 cannot be cast to class java.util.concurrent.ThreadFactory

Jira: https://clojure.atlassian.net/browse/CLJ-2856

closed with the note: Have decided not to do this, at least not in 1.12 scope via implicit conversion
I asked Brian Goetz what was the rational for this in Java, and to my surprise, he answered:

Q: What was the rationale for allowing use of all SAM/SMI in lambdas/method references, and not only those marked as FunctionalInterface? I think it's this disconnect that also causes the confusion about the FunctionalInterface annotation. At least for me, it seems like the annotation is meant to prevent the use of an interface not annotated in an unintended way, yet it does not. And people wonder, how bad is it if I still use it in a lamda?

Brian Goetz: Existing Java libraries are full of SAM interfaces. Requiring a declaration-site opt in would mean, among other things, that these libraries would have to be updated before people could use them as lambda targets. And, for no good reason; these all can be used with single-method anonymous classes, and not allowing lambdas here would just be restrictive for its own sake. As to "how bad would it be", the answer is "not bad at all."