Reputation: 1376
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?
Upvotes: 13
Views: 7456
Reputation: 11
just expand your lambda to an anonymous class:
UnaryOperator<Integer> f = new UnaryOperator<Integer>(){
@Override
public Integer apply(Integer i) {
return i == 0 ? 1 : i * this.apply( i - 1);
}
};
Upvotes: 1
Reputation: 1803
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
Upvotes: 2
Reputation: 33019
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));
}
}
Upvotes: 12