I found this article to be very informative in comparison of old-style functions to new Java-8 lambda-functions and parallel processing. One thing I couldn't quite understand was one restriction on the lambda-functions: From page 4:
3.3 Preconditions Although lambda expressions are intended as a more con- cise alternative to AIC , they are not a complete replacement. There are several preconditions that LambdaFicator checks before refactoring an AIC into a lambda expression. These preconditions are inherent to how lambda expressions are implemented in Java, not limitations of our tool. (P1) AIC must instantiate from an interface. Instances of abstract or concrete classes cannot be converted to lambda expressions. (P2) AIC must have no fields, and declare only one method. A lambda expression represents a single anonymous func- tion; therefore, an AIC with multiple methods can not be converted to a single lambda expression. (P3) AIC must not have references to this or super . In a lambda expression, this and super are lexically scoped, meaning they are interpreted just as they would be in the enclosing environment, e.g., as if they appeared in the state- ment before the lambda expression [6]. However, in an AIC they refer to the inner class itself. (P4) AIC must not declare a recursive method. In order to perform the recursive call, we must obtain a reference to the anonymous function. While LambdaFicator could perform this refactoring, this could introduce unneeded complexity into the code and harm understandability.
On P4, "AIC must not declare a recursive method... LambdaFicator could perform this refactoring...", how could one refactor a lambda expression to reference itself? Since by definition these lambda anonymous-functions don't have a name that can be referenced, and don't have a reference to themselves (P3 above).?
A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function.
Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
You do not have to create a functional interface in order to create lambda function.
public class Test {
static Runnable r;
public static void main(String... args) {
r = () -> r.run();
r.run();
}
}
The Runnable
obtains a reference to itself from the field r
when it is run.
You could also use a length 1 array to store the reference if you don't like adding a field.
As said here, Java’s canonical way to 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 a instance fulfilling a functional interface
you can use a method reference:
Function<Integer, Integer> fib = MyClass::fib;
or
IntUnaryOperator fib0=MyClass::fib;
This is the closest equivalent to a lambda expression as a lambda expression is not just syntactic sugar for a runtime generated class replacing the anonymous inner class but also for an anonymous method hosting the code of the single abstract method to implement.
Using an ordinary recursive method turns the anonymous method into a named one while maintaining all other properties of lambda expressions. This differs from all other workarounds trying to give a lambda expression a reference to itself, like storing the instance into a field. These workarounds are not semantically equivalent (and less efficient).
Derived from @Alex's 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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With