Re: Constructing a java lambda expression?

Alan Ruttenberg <[email protected]> Wed, 24 Aug 2022 12:11:17 -0400
Newsgroups gmane.editors.j.devel
Message-ID <CAFKQJ8=X_3nLDomPcAEh495jfWW7H2B7m9gy+M2pOCTALexn_Q@mail.gmail.com>
--000000000000e5aa6905e6feef2e
Content-Type: text/plain; charset="UTF-8"

This is exactly what I was looking for! I'll give it a try and then see
about integrating something like this into jss.
Thanks so much,
Alan

On Tue, Aug 23, 2022 at 11:10 PM Vibhu Mohindra <[email protected]>
wrote:

> On 23/08/2022 05:27, Alan Ruttenberg wrote:
> > There's a library I want to use that takes a lambda as an argument.
> > Anyone know how to construct one in ABCL?
>
> I assume it's a Java library taking a Java Lambda that you want to call
> from ABCL.
>
> A Java Lambda is really an instance of one of the classes in
> java.util.function. Which one depends on how many parameters it has and
> whether it returns a value. Let's assume your library wants a Java
> Lambda that has one parameter and returns a value. That's a
> java.util.function.Function. Say it looks like this:
>
> //Lib.java
> public class Lib {
>    public static void f(java.util.function.Function f) {
>      System.out.println("You answered: " + f.apply(5));
>    }
> }
>
> such that it can be used from Java with a Java Lambda like this:
>
> Lib.f((Object x) -> (Integer)x * (Integer)x);
> => You answered: 25
>
> You'd like to give it a Lisp Lambda from ABCL as follows:
>
> (jstatic "f" "Lib" #'(lambda (x) (* x x)))
>
> but that's not allowed because although Java can implicitly convert from
> a Java Lambda to a java.util.function.Function, it can't convert from a
> Lisp Lambda to a java.util.function.Function.
>
> A Lisp Lambda is really an org.armedbear.lisp.Function. So one solution
> is to adapt that.
>
> //Adaptor.java
> import org.armedbear.lisp.*;
> public class Adaptor implements java.util.function.Function {
>    private org.armedbear.lisp.Function lispFn;
>    public Adaptor(org.armedbear.lisp.Function lispFunction) {
>      this.lispFn = lispFunction;
>    }
>    public Object apply(Object input) {
>      return lispFn.execute(
>        JavaObject.getInstance(input, true)).javaInstance();
>    }
> }
>
> and use it from ABCL like this:
>
> (jstatic "f" "Lib" (jnew "Adaptor" #'(lambda (x) (* x x))))
> => You answered: 25
> => NIL
>
> ----
> Notes:
>
> I'm on Java 10, ABCL-1.4.0 (which is old).
> I did this to build and run, starting with the jar and two java files in
> the current directory:
> javac -classpath abcl-1.4.0.jar:. Adaptor.java Lib.java
> java -classpath abcl-1.4.0.jar:. org.armedbear.lisp.Main
>  > (jstatic "f" "Lib" (jnew "Adaptor" #'(lambda (x) (* x x))))
>
> You can probably create the Adaptor class from within ABCL if you don't
> like that it's written in Java, but I don't remember how to. ABCL's
> documentation might describe such bytecode generation somewhere.
>
> Pointers:
> Java: java.util.function.*
> ABCL: In org.armedbear.lisp, LispObject, JavaObject, Function
>
>
> --
> Vibhu
>
>

--000000000000e5aa6905e6feef2e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>This is exactly what I was looking for! I&#39;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=3D"=
gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Tue, Aug 23, 2022 at =
11:10 PM Vibhu Mohindra &lt;<a href=3D"mailto:[email protected]">vib=
[email protected]</a>&gt; wrote:<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,20=
4);padding-left:1ex">On 23/08/2022 05:27, Alan Ruttenberg wrote:<br>
&gt; There&#39;s a library I want to use that takes a lambda as an argument=
. <br>
&gt; Anyone know how to construct one in ABCL?<br>
<br>
I assume it&#39;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&#39;s assume your library wants a Java <br>
Lambda that has one parameter and returns a value. That&#39;s a <br>
java.util.function.Function. Say it looks like this:<br>
<br>
//Lib.java<br>
public class Lib {<br>
=C2=A0 =C2=A0public static void f(java.util.function.Function f) {<br>
=C2=A0 =C2=A0 =C2=A0System.out.println(&quot;You answered: &quot; + f.apply=
(5));<br>
=C2=A0 =C2=A0}<br>
}<br>
<br>
such that it can be used from Java with a Java Lambda like this:<br>
<br>
Lib.f((Object x) -&gt; (Integer)x * (Integer)x);<br>
=3D&gt; You answered: 25<br>
<br>
You&#39;d like to give it a Lisp Lambda from ABCL as follows:<br>
<br>
(jstatic &quot;f&quot; &quot;Lib&quot; #&#39;(lambda (x) (* x x)))<br>
<br>
but that&#39;s not allowed because although Java can implicitly convert fro=
m <br>
a Java Lambda to a java.util.function.Function, it can&#39;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>
=C2=A0 =C2=A0private org.armedbear.lisp.Function lispFn;<br>
=C2=A0 =C2=A0public Adaptor(org.armedbear.lisp.Function lispFunction) {<br>
=C2=A0 =C2=A0 =C2=A0this.lispFn =3D lispFunction;<br>
=C2=A0 =C2=A0}<br>
=C2=A0 =C2=A0public Object apply(Object input) {<br>
=C2=A0 =C2=A0 =C2=A0return lispFn.execute(<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0JavaObject.getInstance(input, true)).javaInstanc=
e();<br>
=C2=A0 =C2=A0}<br>
}<br>
<br>
and use it from ABCL like this:<br>
<br>
(jstatic &quot;f&quot; &quot;Lib&quot; (jnew &quot;Adaptor&quot; #&#39;(lam=
bda (x) (* x x))))<br>
=3D&gt; You answered: 25<br>
=3D&gt; NIL<br>
<br>
----<br>
Notes:<br>
<br>
I&#39;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 <b=
r>
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>
=C2=A0&gt; (jstatic &quot;f&quot; &quot;Lib&quot; (jnew &quot;Adaptor&quot;=
 #&#39;(lambda (x) (* x x))))<br>
<br>
You can probably create the Adaptor class from within ABCL if you don&#39;t=
 <br>
like that it&#39;s written in Java, but I don&#39;t remember how to. ABCL&#=
39;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>

--000000000000e5aa6905e6feef2e--