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'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 <<a href=3D"mailto:[email protected]">vib= [email protected]</a>> 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> > 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> =C2=A0 =C2=A0public static void f(java.util.function.Function f) {<br> =C2=A0 =C2=A0 =C2=A0System.out.println("You answered: " + 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) -> (Integer)x * (Integer)x);<br> =3D> 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 fro= m <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> =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 "f" "Lib" (jnew "Adaptor" #'(lam= bda (x) (* x x))))<br> =3D> You answered: 25<br> =3D> 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 <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> (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&#= 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--