Simeon Leyzerzon
Simeon Leyzerzon

Reputation: 19074

Scope in higher order functions in Java 8 lambda syntax of Combinator Pattern

I'm trying to understand the syntax in the create method of the following example:

import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.function.Function;

@FunctionalInterface
interface Before<T, R> extends Function<Consumer<T>, Function<Function<T, R>, Function<T, R>>> {

    static <T, R> Before<T, R> create() {
        return before -> function -> argument -> {
            before.accept(argument);
            return function.apply(argument);
        };
    }

    static <T, R> Function<T, R> decorate(Consumer<T> before, Function<T, R> function) {
        return Before.<T, R>create().apply(before).apply(function);
    }
}

public class BeforeExample {

    void demo() {
        System.out.println("----------------------------------");
        System.out.println("Starting BEFORE combinator demo...");
        System.out.println("----------------------------------");

        Function<BigDecimal, String> addTax = this::addTax;

        Consumer<BigDecimal> before = this::before;

        Function<BigDecimal, String> addTaxDecorated = Before.decorate(before, addTax);

        BigDecimal argument = new BigDecimal("100");
        String result = addTaxDecorated.apply(argument);

        System.out.println("Done - Result is " + result);
        System.out.println();
    }

    private void before(BigDecimal argument) {
        System.out.println("BEFORE: Argument is " + argument);
    }

    private String addTax(BigDecimal amount) {
        System.out.println("Adding heavy taxes to our poor citizen...");
        return "$" + amount.multiply(new BigDecimal("1.22"));
    }
}

Can someone please explain:

Thank you.

Upvotes: 1

Views: 234

Answers (1)

Naman
Naman

Reputation: 31878

what is going on in the return before -> function -> argument -> {...} block and how the variables before, function and argument become known without seemingly being passed in

The following piece of code can help you understand the block and the usage of variables within:

static <T, R> Before<T, R> create() {
    return new Before<T, R>() {
        @Override
        public Function<Function<T, R>, Function<T, R>> apply(Consumer<T> before) {
            return new Function<Function<T, R>, Function<T, R>>() {
                @Override
                public Function<T, R> apply(Function<T, R> function) {
                    return new Function<T, R>() {
                        @Override
                        public R apply(T argument) {
                            before.accept(argument);
                            return function.apply(argument);
                        }
                    };
                }
            };
        }
    };
}

what the multiple -> signify.

The lambda representation for each of those functional interfaces combined to represent the implementation of create method.

Upvotes: 1

Related Questions