Simeon Leyzerzon
Simeon Leyzerzon

Reputation: 19074

Performing side-effects in Vavr

I'm going through Vavr Usage Guide's section about performing side-effects with Match and other "syntactic sugar" as they call it. Here is the example given there:

Match(arg).of(
    Case($(isIn("-h", "--help")), o -> run(this::displayHelp)),
    Case($(isIn("-v", "--version")), o -> run(this::displayVersion)),
    Case($(), o -> run(() -> {
        throw new IllegalArgumentException(arg);
    }))
);

and then it goes into discussing how run should not be run outside of lambda body, etc.

IMHO, something was lacking in the explanation to give me full clarity, i.e. is run an existing method on some Vavr interface (which I couldn't find) or should it be my own method in the surrounding code base?

So I endeavored and spelled out the above example just slightly to be something that I can run and see the results of it:

@Test public void match(){

String arg = "-h";

        Object r = Match(arg).of(
                Case($(isIn("-h", "--help")), o -> run(this::displayHelp)),
                Case($(isIn("-v", "--version")), o -> run(this::displayVersion)),
                Case($(), o -> run(() -> {
                    throw new IllegalArgumentException(arg);
                }))
            );

        System.out.println(r);
    }

    private Void run(Supplier<String> supp) {
        System.out.println(supp.get());
        return null;}

    private String displayHelp() {return "This is a help message.";}
    private String displayVersion() {return "This is a version message.";}

Could someone please confirm that I'm on the right track with how this was envisioned to function by Vavr's designers or did I totally go off on a tangent in which case I'd appreciate some guidance as to how it should be.

Thank you in advance.

Updated:

import static io.vavr.API.run;

    @Test public void match1() {

            String arg = "-h";

            Object r = Match(arg).of(
                    Case($(isIn("-h", "--help")), o -> run(this::displayHelp)),
                    Case($(isIn("-v", "--version")), o -> run(this::displayVersion)),
                    Case($(), o -> run(() -> {
                        throw new IllegalArgumentException(arg);
                    }))
                );

            System.out.println("match: " +r);
        }

        //private Void run(Supplier<Void> supp) {supp.get();}

        private void displayHelp() {System.out.println("This is a help message.");}
        private void displayVersion() {System.out.println("This is a version message.");}

Upvotes: 2

Views: 1193

Answers (1)

HTNW
HTNW

Reputation: 29193

It's io.vavr.API.run. According to the Javadoc, you're supposed to import the basic VAVR functionality via

import static io.vavr.API.*;

The run function calls a Runnable (a function () -> void) once and returns (Void)null. It's used because

Case($(isIn("-h", "--help")), o -> this.displayHelp())

does not work when displayHelp() is void, since void isn't a well-behaved type in Java. Specifically, Supplier<void> and Function<?, void> do not work. Additionally,

Case($(isIn("-h", "--help")), this.displayHelp())

would execute displayHelp() before the match, so the matching is useless. This rules out all three (ignoring argument number) overloads of Case. run fixes this, because Supplier<Void> and Function<?, Void> are possible, and taking a Runnable means the action can be deferred until the argument to Case is needed.

Upvotes: 6

Related Questions