How can there be a link to a Java lambda expression?

I found this article to be very informative when comparing old-style functions with the new Java-8 lambda functions and parallel processing. The only thing I could not understand was this one restriction on lambda functions: from page 4:

3.3 Prerequisites Although lambda expressions are intended as a more alternative AIC, they are not a complete replacement. There are several preconditions that a LambdaFicator checks before refactoring AIC into a lambda expression. These prerequisites are inherent in the way lambda expressions implemented in Java, and not the limitations of our tool. (P1) AIC must be created from the interface. Instances of abstract or concrete classes cannot be converted to lambda expressions. (P2) AICs must not have fields and declare only one method. The expression lambda is one anonymous function, Tion; therefore, an AIC with multiple methods cannot be converted to a single lambda expression. (P3) AICs should not have references to this or super, In a lambda expression, this as well as super lexically covered that they are interpreted in the same way as in the environment, for example, as if they appeared in the state before the lambda- expression [6]. However, in AIC they belong to the innermost class. (P4) AIC should not declare a recursive method. To make a recursive call, we need to get a link to an anonymous function. While LambdaFicator can do this refactoring, it can introduce unnecessary complexity into the code and understandability of harm.

In P4, "AIC should not declare a recursive method ... LambdaFicator could do this refactoring ...", how could a lambda expression be reorganized to refer to itself? Since, by definition, these lambda-anonymous functions do not have a name that can be referenced, and do not have a reference to themselves (P3 above).?

+6
source share
3 answers
public class Test { static Runnable r; public static void main(String... args) { r = () -> r.run(); r.run(); } } 

Runnable gets a reference to itself from the r field when it starts.

You can also use an array of length 1 to store the link if you don't like adding a field.

+2
source

Retrieved from @Alex answer:

 @FunctionalInterface public interface SelfRunnable extends Runnable { public void run(SelfRunnable this_); @Override public default void run() { run(this); } public static Runnable runnable(SelfRunnable runnable) { return runnable; } } public interface Test { public static void main(String... arguments) { final Runnable r = SelfRunnable.runnable(this_ -> this_.run()); r.run(); } } 
+1
source

As stated here , the canonical way Javas implement a recursive function is a method:

 public static int fib(int n) { return n==0? 0: n==1? 1: fib(n-1)+fib(n-2); } 

Then, if you need an instance that executes a functional interface , you can use the method reference:

 Function<Integer, Integer> fib = MyClass::fib; 

or

 IntUnaryOperator fib0=MyClass::fib; 

This is the closest equivalent to a lambda expression, because the lambda expression is not just syntactic sugar for the generated runtime class that replaces the anonymous inner class, but also for the anonymous method, which hosts the code for a single abstract method for implementation.

Using the usual recursive method turns an anonymous method into a named one, while preserving all the other properties of lambda expressions. This is different from all other workarounds, trying to give a lambda expression a reference to itself, for example, saving an instance in a field. These workarounds are not semantically equivalent (and less efficient).

+1
source

Source: https://habr.com/ru/post/980483/


All Articles