Javaslang - как мне присоединиться к двум успешным Trys? - PullRequest
1 голос
/ 17 октября 2019

Я все еще изучаю Javaslang / Vavr, так что извините за невежество. Проект, над которым я работаю, застрял на Javaslang 2.1.0 .

Мой вопрос: есть ли более «функциональный» (в отличие от императивного стиля) способ структурировать мой код так, чтобыприсоединиться к нескольким попыткам только после того, как они успешны?

Я хочу попробовать каждый ввод независимо, идея состоит в том, чтобы получить как можно больше информации об ошибках - я делаю не хочу остановиться на первой обнаруженной ошибке (поэтому orElse() и т. д. не помогут). Но как только ошибки больше не обнаруживаются, я хочу сделать что-то еще, включая все входные данные.

Мой текущий код выглядит следующим образом (соответственно анонимно):

Try<BigDecimal> amountTry = Try.of(this::readNumber)
    .map(BigDecimal::valueOf)
    .onFailure(this::collectError);

Try<Currency> currencyTry = Try.of(this::readString)
    .map(currency -> currencyLookup(Currency.class, currency))
    .onFailure(this::collectError);

if (amountTry.isSuccess() && currencyTry.isSuccess()) {
    sale.setAmount(Amount.of(amountTry.get(), currencyTry.get()));
}

Можете ли вы предложитьшаблон для замены if() на что-то большее в функциональном стиле программирования?

1 Ответ

2 голосов
/ 17 октября 2019

Конструкция Javaslang / Vavr, которую вы ищете, является конструкцией для понимания , которая доступна с помощью методов API.For.

import javaslang.control.Try;
import static javaslang.API.For;
...

For(amountTry, currencyTry)
    .yield(Amount::of)
    .forEach(sale::setAmount);

То есть, если оба amountTry и currencyTry не являются пустыми, он создает Iterable, получая значение результата для перекрестного произведения двух итераций и выполняя действие для каждого из полученных элементов, вызывая Consumer. Вот то же самое в лямбда-форме с явными типами ввода, если это поможет вам лучше понять это:

For(amountTry, currencyTry)
    .yield((BigDecimal amount, Currency currency) -> Amount.of(amount, currency))
    .forEach((Amount amount) -> sale.setAmount(amount));

Более поздние версии библиотеки имеют перегрузки для понимания для Try, которые возвращают Try экземпляр вместо Iterable, что делает API немного лучше, если вы хотите остаться в Try домене.

...