I just wanted to define a Java 8 lambda expression recursively.
The Lambda FAQ mentions that one can define a recursive lambda expression only during (static) field initialization.
But I get a compiler error in IntelliJ (javac just reports an error without a message):
java: self-reference in initializer
If I try to write something like:
static UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * f.apply( i - 1);
or
UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * f.apply( i - 1);
One way I found to make it work was to use an array for referencing the lambda effectively tricks the java compiler:
import java.util.function.UnaryOperator;
public class RecursiveLambdaExample {
public static void main(String[] args) {
UnaryOperator<Integer>[] fac = new UnaryOperator[1];
fac[0] = i -> i == 0 ? 1 : i * fac[0].apply( i - 1);
UnaryOperator<Integer> factorial = fac[0];
System.out.println(factorial.apply(5));
}
}
Is there another trick to define recursive lambda expression?
This is an example of a function that will recursively call itself. Warning It's possible to run into infinite loops with recursive calls. Test your functions locally before deploying to production.
Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection .
Lambda Expressions were added in Java 8. 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.
You can make it work by fully-qualifying the field name that you're referencing recursively. This version compiles without any error:
import java.util.function.UnaryOperator;
public class RecursiveLambdaExample {
static UnaryOperator<Integer> fac = i -> i == 0 ? 1 : i * RecursiveLambdaExample.fac.apply( i - 1);
UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * this.f.apply( i - 1);
public static void main(String[] args) {
System.out.println(new RecursiveLambdaExample().f.apply(5));
System.out.println(fac.apply(5));
}
}
Related: Why do lambdas in Java 8 disallow forward reference to member variables where anonymous classes don't?
You are able to achieve this with nested class:
public class Main {
public static void main(String[] args) {
class Helper {
final UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * this.f.apply( i - 1);
}
System.out.println(new Helper().f.apply(3));
}
}
output:
6
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