Лямбда с побочным эффектом
От: f95.2  
Дата: 09.05.20 12:43
Оценка:
Насколько я знаю, в java нет методаожидания с предикатом, аналога std::condition_variable::wait из c++.

Допустим, я написал такой метсод с сигнатурой:
public void TimedWait(Object monitor, long timeout_msec, BooleanSupplier condition);


Далее, допустим, предикат внутри себя вычисляет какое-то значение, если оно не равно плохому, то возвращает true (т.е. необходимость остановить ожидание).
{
    ValueType value = calculateValue();
    return value.equals(badValue);
}


Предикат хочется сделать лямбдой, т.к. он маленький.

Допуcтим также, что, пока значение равно плохому, то calculateValue отрабатывает нормально и быстро, но после того, как будет получено нужное значение,
данные, из которых оно вычислено, необратимо меняются, и снова значение не получить.

Ну и наконец, допустим, что я хочу получить это значение после того, как отработал метод TimedWait.
Вопрос: как это сделать?

Допущения проистекают от дерьмового дизайна системы, и я этот дизайн переделаю, но остается чисто академический интерес.

А проблема вытащить занчение в том, что в лямбду можно передавать только константные переменные,
так что через замыкание вернуть значение красиво нельзя.

Варианты, которые вижу я:
1. Сделать какую-то обертку над значением, например, массив из одного элемента, или специальный класс,
его передать в предикат (ссылка на эту обертку будет константной), и в предикате выставить значение.

Т.е. как-то так:
ValueType[] wrapper = new ValueType[1];

TimedWait(monitor, timeout_msec, () -> {
    wrapper[0] = calculateValue();
    return !wrapper[0].equals(ифвValue);
});


Недостаток — выглядит криво.

2. Сделать предикат не лямбдой, а полноценным объектом спец. класса, значение передавать через поле класса.
Недостаток — лишний класс, слишком много лишнего кода.

3. Сделать доп. функцию (рядом с calculateValue), которая где-то сохраняет переданное значение, и вызывать ее внутри предиката.
Недостаток — лишняя функция, лишнее поле класса. Криво, в общем.

Мб есть какой-то красивый и идиоматичный способ решить подобную проблему.
Или вообще отказаться от лямбды с побочным эффектом, а сделать как-то еще?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.