Pattern matching w Javie z Javaslang II

Poprzednie części:

Dopasowanie wzorców do wartości jest w sumie proste. Podobny efekt można uzyskać stosując mapy. Jednak Javaslang udostępnia też API, w którym dopasowanie oparte jest o predykaty. Przy czym są to predykaty biblioteki, a nie Javy 8.

Listing 1. Dopasowanie z wykorzystaniem predykatu

public void predicates() {
    Integer i = 0;
    String on = Match(i).of(
            Case(x -> x == 1, "Jeden"),
            Case(x -> x == 2, "Dwa"),
            Case($(), "?")
    );
    System.out.println(on);
}

Predykaty z API

Oczywiście API Javaslang udostępnia nam cały zestaw predykatów, których możemy użyć „od ręki”:

Listing 2. Przykładowe predykaty z API

public void predicates2(Object i) {
    String on = Match(i).of(
            Case(is(1), "Jeden"),
            Case(isIn(2, 3), "Dwa albo 3"),
            Case(anyOf(is(4), noneOf(is(5), is(6))), "4 lub nie (5 lub 6)"),
            Case(instanceOf(String.class), "Jakiś napis"),
            Case($(), "?")
    );
    System.out.println(on);
}

Do wyboru, do koloru. Predykaty można łączyć na wiele sposobów. anyOf, noneOf to tylko dwa z kilku dostępnych.

Wartości zwracane

Dotychczas patrzyliśmy tylko na to, jak można zdefiniować dopasowanie. Wartość zwracana z warunku była na sztywno zapisana w kodzie. Zamiast tego można użyć funkcji i Supplierów z API Javy 8:

Listing 3. Przykładowe zwracanie wartości

public void returnig() {
    Integer i = 1;
    String on = Match(i).of(
            Case($(1), v -> v + ""),
            Case($(2), () -> "Dwa"),
            Case($(), "?")
    );
    System.out.println(on);
}

Efektywnie Match zachowuje się jak wyrażenie i musi zwrócić wartość. Co w przypadku gdy zamiast zwracania wartości chcemy wykonać jakąś czynność? W tym przypadku musimy użyć metody pomocniczej run:

Listing 4. Użycie run w celu uruchomienia kodu

public void running() {
    Integer i = 1;
    Void of = Match(i).of(
            Case($(1), x -> run(()->System.out.println(x))),
            Case($(2), x -> run(()->System.out.println(x))),
            Case($(), () -> null)
    );
}

Krytycznym wymaganiem jest opakowanie run w Supplier. W przeciwnym wypadku zostanie on uruchomiony przed procedurą dopasowania. Dlaczego? Ponieważ ewaluacja parametrów w Javie jest zachłanna.

Podsumowanie

Jak widać, dopasowanie wzorców w wersji Javaslang jest dobrze rozwinięte i pozwala na uzyskanie wielu rozwiązań, które są znane z języków, gdzie mechanizm ten jest częścią samego języka.

3 myśli na temat “Pattern matching w Javie z Javaslang II

  1. I think in running() that Case($(1), () -> run(System.out::println)) should really be Case($(1), x -> run(() -> System.out.println(x))) to see some printed output

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax