1

I am trying to make a lambda function that references itself, and it is used as a callback for an asynchronous process, so I cannot use a loop. If I declare the function like so :

Consumer<String> func = argument -> {
    async_fn(func); // Call a function with func as callback
};

the compiler tells me The local variable func may not have been initialized. If I write it that way instead :

Consumer<String> func = argument -> {}; // pre-declare func
func = argument -> {
    async_fn(func); // Call an function with func as callback
};

the compiler says local variables referenced from a lambda expression must be final or effectively final. How could this be written so that the function references itself ? The function cannot be a class field because it references a method's locals.

1
  • 4
    A better question: why would you want a lambda function to recurse? Because that's kind of a sign something's gone wrong. What are you actually trying to do that you thought "I can use a lambda function for that", because this is almost certainly an XY Problem, where you're asking about how to fix your solution to your original problem, instead of explaining your original problem in your post, too, so we can help you solve that one properly. Commented Jun 2, 2021 at 23:18

3 Answers 3

1

Although I do not understand why such a construct would be needed, you could do:

    Consumer<String> func = argument -> {}; // pre-declare func
    List<Consumer<String>> one = new ArrayList<>(Collections.singletonList(func));
    one.set(0, argument -> {
        async_fn(one.get(0)); // Call an function with func as callback
    });

Or use an array.

Sign up to request clarification or add additional context in comments.

2 Comments

The reassigment at line 3 does not affect the func contained in one
The func function is unnecessary. You don't need to put a function in your list just to replace it in the next line.
1

It smells like a code smell, but there are ways to achieve what you want.

The first one - you can make an ordinary method that calls itself, and you call it from a lambda that passes variables from the local context. That's probably the cleanest way.

An alternative is to use local array variables, as the contents of an array can be modified even when the array itself is (effectively) final:

Consumer<String>[] func = (Consumer<String>[]) new Consumer<?>[1];
func[0] = argument -> {
    async_fn(func[0]); // Call an function with func as callback
};

Or you can store the reference to your lambda in a field of your object:

private Consumer<String> func;

public void mymethod() {
    func = argument -> {
        async_fn(func); // Call an function with func as callback
    };
}

Comments

1

Consider not using a lambda, but an anonymous class.

Consumer<String> func = new Consumer<String>() {
  @Override public void accept(String str) {
    asyncFn(this, str);
  }
};

No need for adding the object to another mutable variable later; an anonymous inner class can just use this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.