Constructing a java lambda expression?
Alessio Stalla
alessiostalla at gmail.com
Thu Aug 25 10:35:17 UTC 2022
Because *andThen *is a *default method *in the interface, i.e. it's not
abstract:
https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
So, effectively, the interface only has one abstract method, and that's the
target of lambda conversion.
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.
On Thu, 25 Aug 2022 at 06:37, Alan Ruttenberg <alanruttenberg at gmail.com>
wrote:
> So in order to implement this I need to know the interface to use for the
> lambda? Presumably I can determine this with reflection.
>
> An example of one of the functions that takes the lambda is defined:
>
> public final NitfSegmentsFlow forEachImageSegment(final
> Consumer<ImageSegment> consumer)
>
> But consumer has two methods: accept and andThen
>
> 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?
>
> What confuses me now is if a lambda is passed as the test code I'm reading
> does:
>
> forEachImageSegment(imageSegment -> {do something})
>
> 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?
>
> Thanks,
> Alan
>
>
> On Wed, Aug 24, 2022 at 4:14 AM Alessio Stalla <alessiostalla at gmail.com>
> wrote:
>
>> 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:
>>
>> new Thread(() -> { System.out.println("foo"); }).run();
>>
>> The Thread constructor takes a Runnable argument, not a Function.
>>
>> Lambda is just syntax sugar for interfaces with a single method, so you
>> can reproduce them on ABCL with the jinterface thing + some macrology.
>>
>> On Wed, 24 Aug 2022 at 05:10, Vibhu Mohindra <vibhu.mohindra at gmail.com>
>> 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
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/armedbear-devel/attachments/20220825/89970db2/attachment-0001.html>
More information about the armedbear-devel
mailing list