<div dir="ltr"><div>This is exactly what I was looking for! I'll give it a try and then see about integrating something like this into jss. <br></div><div>Thanks so much,</div><div>Alan<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 23, 2022 at 11:10 PM Vibhu Mohindra <<a href="mailto:vibhu.mohindra@gmail.com">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>