0

I have written a function which I see great potential in being a recursive lambda function but I just can't wrap my head around how to implement it myself. The reason why I want to convert it to a recursive lambda function is the ability for me to run it for as long as I want where as currently I would have to copy paste another segment of code.

    private void crack()
    {
        System.out.println("Trying 1 mangle");
        wordList.forEach(
                x -> Mangle.getAllMangles(x).forEach(this::checkAllVictims)
        );
        System.out.println("Trying 2 mangles");
        wordList.forEach(
                x -> Mangle.getAllMangles(x).forEach(
                        y -> Mangle.getAllMangles(y).forEach(this::checkAllVictims)
                )
        );
        System.out.println("Trying 3 mangles");
        wordList.forEach(
                x -> Mangle.getAllMangles(x).forEach(
                        y -> Mangle.getAllMangles(y).forEach(
                                z -> Mangle.getAllMangles(z).forEach(this::checkAllVictims)
                        )
                )
        );
    }

How would one go about refactoring this function the best way possible?

From a course on functional programming with Elixir a year ago I did something similar but I do not know how to apply the same principle here.

def to_church(0) do
    fn(_), y -> y end
end
def to_church(n) do
    fn(f, x) -> f.(to_church(n - 1).(f, x)) end
end

The whole Elixir code can be found here if more context is needed.

Another issue I have had, which is not the main issue of this question but would be a cherry on top to have answered, is that when running the above code in parallel as part of a Runnable object in an ExecutorService thread pool (run() calls crack()) all the threads except the first one allocated stops executing after printing "Trying 1 mangle". They simply just dissapear without a trace and I do not know why.

Silop
  • 5
  • 5

2 Answers2

0

I came up with somewhat of a solution.

I created a new class which implemented BiConsumer<List, Integer>.

public Mangler(final Cracker c)
{
    this.c = c;
}

public void start(String s, int i)
{
    accept(Mangle.getAllMangles(s), i - 1); 
}

@Override
public void accept(List<String> strings, Integer integer)
{
    if (integer == 0) {
        strings.forEach(x -> c.checkAllVictims(x));
        return;
    }
    strings.forEach(x -> this.accept(Mangle.getAllMangles(x), integer - 1));
}

Which I could then call in the crack() function of my Cracker class:

Mangler m = new Mangler(this);
dictionary.parallelStream().forEach(word -> m.start(word, 1));
dictionary.parallelStream().forEach(word -> m.start(word, 2));
dictionary.parallelStream().forEach(word -> m.start(word, 3));

I also changed the parallelism to apply only to the dictionary of the Cracker instead of making the whole class a Runnable.

Silop
  • 5
  • 5
-1

See Implement recursive lambda function using Java 8 as well as https://pysaumont.github.io/2014/09/01/Recursive-lambdas-in-Java-8.html and https://dzone.com/articles/do-it-java-8-recursive-lambdas and https://coderanch.com/t/634917/java/Recursion-Lambda-Java. Seems that you should find at least one viable solution.