<div dir="ltr"><div><span style="font-family:arial,sans-serif">Thanks.</span></div><div><span style="font-family:arial,sans-serif"><br></span></div>(defun get-abstract-methods (classname)<br> (map 'list #"getName"<br> (remove-if-not <br> (lambda(x) <br> (let ((modifiers (#"getModifiers" x)))<br> (and (#"isAbstract" 'reflect.Modifier modifiers)<br> (not (#"isStatic" 'reflect.Modifier modifiers)))))<br><div> (#"getDeclaredMethods" (find-java-class classname)))))</div><div><br></div>(defun java-lambda-parameter-information (classname methodname position)<br> (let* ((method (find methodname (#"getDeclaredMethods" (find-java-class classname))<br> :key #"getName" :test 'equalp))<br> (parameter-type (elt (#"getParameterTypes" method) position))<br> (abstract-methods (get-abstract-methods parameter-type)))<br> (assert (#"isInterface" parameter-type) ()<br> "lambda parameter type ~a should be an interface but isn't" <br> (#"getName" parameter-type))<br> (assert (= (length abstract-methods) 1) ()<br> "Parameter ~a type ~a has more than one abstract method: ~{~a~^, ~}"<br> position (#"getName" parameter-type) abstract-methods)<br> (list (#"getName" parameter-type) (car abstract-methods))))<div><span style="font-family:monospace"><br></span></div><div><span style="font-family:arial,sans-serif">(java-lambda-parameter-information 'Nitfsegmentsflowimpl "forEachImagesegment" 0)<br>-> ("java.util.function.Consumer" "accept")</span></div><div><br></div><div><font size="2">Cheers,</font></div><div><font size="2">Alan</font><br></div><div><div><span style="font-family:monospace"><br></span></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Aug 25, 2022 at 6:35 AM Alessio Stalla <<a href="mailto:alessiostalla@gmail.com">alessiostalla@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Because <i>andThen </i>is a <b>default method </b>in the interface, i.e. it's not abstract: <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html" target="_blank">https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html</a></div><div>So, effectively, the interface only has one abstract method, and that's the target of lambda conversion.</div><div>Now I have no idea if and how ABCL deals with default methods. If it's still stuck on Java 5/6 compatibility then I suspect that it can't, at least not in its Java code.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 25 Aug 2022 at 06:37, Alan Ruttenberg <<a href="mailto:alanruttenberg@gmail.com" target="_blank">alanruttenberg@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>So in order to implement this I need to know the interface to use for the lambda? Presumably I can determine this with reflection.<br></div><div><br></div><div>An example of one of the functions that takes the lambda is defined:</div><div><br></div><div>public final NitfSegmentsFlow forEachImageSegment(final Consumer<ImageSegment> consumer) <br></div><div><br></div><div>But consumer has two methods: accept and andThen <br></div><div><br></div><div>Eventually it looks like accept is called on the consumer. So in this case it looks like I need to use jinterface-implementation and define the accept method, no lambda necessary?</div><div><br></div><div>What confuses me now is if a lambda is passed as the test code I'm reading does:</div><div><br></div><div>forEachImageSegment(imageSegment -> {do something})</div><div><br></div><div>How does java know that the lambda is the implementation of accept rather than andThen. Or more practically, how do I figure out which method to implement without reading the source code?<br></div><div><br></div><div>Thanks,<br></div><div>Alan</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Aug 24, 2022 at 4:14 AM Alessio Stalla <<a href="mailto:alessiostalla@gmail.com" target="_blank">alessiostalla@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Function is a convenient interface for cases when a more specific interface does not exist. But any Java interface with a single abstract method can be the target of a lambda expression:</div><div><pre style="background-color:rgb(255,255,255);color:rgb(0,0,0);font-family:"JetBrains Mono",monospace"><span style="color:rgb(0,0,128);font-weight:bold">new </span>Thread(() -> { System.<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">out</span>.println(<span style="color:rgb(0,128,0);font-weight:bold">"foo"</span>); }).run();</pre></div><div>The Thread constructor takes a Runnable argument, not a Function.</div><div><br></div><div>Lambda is just syntax sugar for interfaces with a single method, so you can reproduce them on ABCL with the jinterface thing + some macrology.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 24 Aug 2022 at 05:10, Vibhu Mohindra <<a href="mailto:vibhu.mohindra@gmail.com" target="_blank">vibhu.mohindra@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 23/08/2022 05:27, Alan Ruttenberg wrote:<br>
> There's a library I want to use that takes a lambda as an argument. <br>
> Anyone know how to construct one in ABCL?<br>
<br>
I assume it's a Java library taking a Java Lambda that you want to call <br>
from ABCL.<br>
<br>
A Java Lambda is really an instance of one of the classes in <br>
java.util.function. Which one depends on how many parameters it has and <br>
whether it returns a value. Let's assume your library wants a Java <br>
Lambda that has one parameter and returns a value. That's a <br>
java.util.function.Function. Say it looks like this:<br>
<br>
//Lib.java<br>
public class Lib {<br>
public static void f(java.util.function.Function f) {<br>
System.out.println("You answered: " + f.apply(5));<br>
}<br>
}<br>
<br>
such that it can be used from Java with a Java Lambda like this:<br>
<br>
Lib.f((Object x) -> (Integer)x * (Integer)x);<br>
=> You answered: 25<br>
<br>
You'd like to give it a Lisp Lambda from ABCL as follows:<br>
<br>
(jstatic "f" "Lib" #'(lambda (x) (* x x)))<br>
<br>
but that's not allowed because although Java can implicitly convert from <br>
a Java Lambda to a java.util.function.Function, it can't convert from a <br>
Lisp Lambda to a java.util.function.Function.<br>
<br>
A Lisp Lambda is really an org.armedbear.lisp.Function. So one solution <br>
is to adapt that.<br>
<br>
//Adaptor.java<br>
import org.armedbear.lisp.*;<br>
public class Adaptor implements java.util.function.Function {<br>
private org.armedbear.lisp.Function lispFn;<br>
public Adaptor(org.armedbear.lisp.Function lispFunction) {<br>
this.lispFn = lispFunction;<br>
}<br>
public Object apply(Object input) {<br>
return lispFn.execute(<br>
JavaObject.getInstance(input, true)).javaInstance();<br>
}<br>
}<br>
<br>
and use it from ABCL like this:<br>
<br>
(jstatic "f" "Lib" (jnew "Adaptor" #'(lambda (x) (* x x))))<br>
=> You answered: 25<br>
=> NIL<br>
<br>
----<br>
Notes:<br>
<br>
I'm on Java 10, ABCL-1.4.0 (which is old).<br>
I did this to build and run, starting with the jar and two java files in <br>
the current directory:<br>
javac -classpath abcl-1.4.0.jar:. Adaptor.java Lib.java<br>
java -classpath abcl-1.4.0.jar:. org.armedbear.lisp.Main<br>
> (jstatic "f" "Lib" (jnew "Adaptor" #'(lambda (x) (* x x))))<br>
<br>
You can probably create the Adaptor class from within ABCL if you don't <br>
like that it's written in Java, but I don't remember how to. ABCL's <br>
documentation might describe such bytecode generation somewhere.<br>
<br>
Pointers:<br>
Java: java.util.function.*<br>
ABCL: In org.armedbear.lisp, LispObject, JavaObject, Function<br>
<br>
<br>
-- <br>
Vibhu<br>
<br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>