Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 lambda (from javascript example)

I'm learning java from javascript background, and I wonder is it possible to write similar function in Java. Here is an example in javascript:

function getBalance(side, date) {
    let balance;
    let getPrice = (f) => {
        while ((result = f(date)) == 0) {
            date++;
        }
        return result;
    }
    if (side) {
        let price = getPrice(getPrice1);
        // Some calculations
        return balance;
    } else {
        let price = getPrice(getPrice2);
        // Some calculations
        return balance;
    }
}

Where getPrice1 and getPrice2 are previously defined functions. Use of calbacks here helps to keep code short. Im not sure is it possible in Java to pass function as argument without declaring additional interfaces.

I asked this question because it is a simplified example of a real task that I encountered. What do you think will be the most elegant solution?

P.S. Looks like Functional Interfaces is the way here.

like image 539
sweetshot Avatar asked Mar 02 '23 17:03

sweetshot


2 Answers

Here's a solution that looks quite close to the javascript code:

import java.time.LocalDate;

public class Showcase {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();

        double result1 = getPrice(priceFunction1, date);
        double result2 = getPrice(priceFunction2, date);
    }

    private static double getPrice(PriceFunction priceFunction, LocalDate date) {
        return priceFunction.getPrice(date);
    }

    private static final PriceFunction priceFunction1 = date -> date.getYear() * 0.5;
    private static final PriceFunction priceFunction2 = date -> date.getYear() * 1.5;

    @FunctionalInterface
    private interface PriceFunction {
        double getPrice(LocalDate date);
    }
}

Instead of using the standard functional interfaces from the java language, like Function, simply define a new functional interface that exactly fulfills the requirements of your function: it takes a date and returns a double value.

The getPrice function takes such a 'function' as the first argument, then we have to pass the date (javascript scopes make it a bit easier there...). The 'functions' themselves are lambda expressions and we can store them as fields or static constants.

The purist may scream that I didn't choose a screaming case for the names, but I'd deviate from the common naming conventions on purpose for the sake of readability.

like image 61
Andreas Dolk Avatar answered Mar 05 '23 14:03

Andreas Dolk


Yes, it's possible.

Here's a dummy showcase just to illustrate how things can be put together.

class Showcase {

    public static void main(String[] args) {
        Function<Function<LocalDate, Double>, Double> getPrice = f -> {
            // an example how to call it - replace it with your logic
            f.apply(LocalDate.now());

            return 0.;
        };

        getPrice.apply(Showcase::getPrice1);
        getPrice.apply(Showcase::getPrice2);
    }

    public static Double getPrice1(LocalDate date) {
        return 0.;
    }

    public static Double getPrice2(LocalDate date) {
        return 1.;
    }

}

It would be more verbose because of the typing discipline. However, the idea is fundamentally the same.

like image 39
Andrew Tobilko Avatar answered Mar 05 '23 15:03

Andrew Tobilko