Re[6]: Класс для возврата значения из лямбды
От: vsb Казахстан  
Дата: 10.01.23 13:02
Оценка:
Здравствуйте, gyraboo, Вы писали:

G>Туплы — это разве не антипаттерн в бизнесовом исходном коде? Особенно когда начинаются триплы и прочие n-туплы, код становится нечитаемой кашей, потому что туплы не содержат семантики, одно только нагромождение этих элементов с бессмысленными названиями. Не станет ли код понятнее, если использовать семантический паттерн Parameter Object?


Ну я его в итоге и использовал. Не знаю. По-мне 2-3 объекта с разными типами — нормально. Но видимо создатели жавы считают, что не нормально.
Re[4]: Класс для возврата значения из лямбды
От: vsb Казахстан  
Дата: 10.01.23 13:07
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, vsb, Вы писали:


vsb>>В итоге объявил прямо в методе record с нужным числом полей и возвращаю его, как одно значение, агрегирующее остальные. Думаю, это самый подходящий вариант.

·>А чем анонимные типы-то не подошли?

Подойти-то подошли, но всё же это мне кажется чем-то на грани хака. Человек, который жаву знает не слишком хорошо, скорей всего не поймёт, что тут вообще происходит. Я считаю, что код надо писать максимально просто и понятно. На мой взгляд с record-ами получилось понятней.

record Val1AndVal2(String val1, String val2) {}
var result = executeWithTxn(txn -> {
    final String val1 = "val1 in " + txn;
    final String val2 = "val2 in " + txn;
    return new Val1AndVal2(val1, val2);
});
System.out.println(result.val1());
System.out.println(result.val2());


Есть ещё такой прикол из той же серии:

var map = new HashMap<String, Integer>(){{
  put("a", 1);
  put("b", 2);
}};


типа псевдо-литерал для инициализации. Но, как мне кажется, далеко не каждый поймёт, что тут произошло, что за двойные фигурные скобки. Поэтому лучше так не писать.

А то так и до оператора "стрелочка" можно дойти:

n = 10;
while (n --> 0) { ... }
Re[7]: Класс для возврата значения из лямбды
От: gyraboo  
Дата: 10.01.23 14:14
Оценка:
Здравствуйте, vsb, Вы писали:

G>>Туплы — это разве не антипаттерн в бизнесовом исходном коде? Особенно когда начинаются триплы и прочие n-туплы, код становится нечитаемой кашей, потому что туплы не содержат семантики, одно только нагромождение этих элементов с бессмысленными названиями. Не станет ли код понятнее, если использовать семантический паттерн Parameter Object?


vsb>Ну я его в итоге и использовал. Не знаю. По-мне 2-3 объекта с разными типами — нормально. Но видимо создатели жавы считают, что не нормально.


Создатели Джавы же ориентированы на бизнес-сегмент, на реализацию бизнес-логики и на то, чтобы писать поддерживаемый код. Туплы же ведут к тяжело читаемому и тяжело поддерживаемому коду, разве не так? Может где-то туплы и выигрывают в плане универсальности, если речь про реализацию каких-то универсальных алогоритмов, где "тупл" сам по себе является "сущностью", но в плане читаемости в бизнес-коде, оперирующем бизнес-сущностями, туплы проигрывают, потому что туплы начинают нести в себе эти бизнес-сущности, а название у них остаётся универсальным и не раскрывает смысл, поэтому например можно легко совершить в коде ошибку и скажем перепутать местами значения одинаковых элементов, да и сама работа с элементами тут не очевидна, т.к. не раскрывается их смысл. Даже если это 2-3 объекта, это уже плохо и непонятно, потому что приходится держать "в уме", что за бизнес-семантика в этих элементах.
Re[5]: Класс для возврата значения из лямбды
От: · Великобритания  
Дата: 10.01.23 14:48
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>>>В итоге объявил прямо в методе record с нужным числом полей и возвращаю его, как одно значение, агрегирующее остальные. Думаю, это самый подходящий вариант.

vsb>·>А чем анонимные типы-то не подошли?
vsb>Подойти-то подошли, но всё же это мне кажется чем-то на грани хака. Человек, который жаву знает не слишком хорошо, скорей всего не поймёт, что тут вообще происходит.
В том же шарпе есть эти же анонимные типы. Там даже страшнее выглядит и типы полей не видны:
var apple = new { Item = "apples", Price = 1.35 };

И ничё, все любят и нахваливают.

vsb>Я считаю, что код надо писать максимально просто и понятно. На мой взгляд с record-ами получилось понятней.

В общем-то да, просто дублирования (а значит и потенциальных мест для опечаток) чуток больше.

vsb>типа псевдо-литерал для инициализации. Но, как мне кажется, далеко не каждый поймёт, что тут произошло, что за двойные фигурные скобки. Поэтому лучше так не писать.

А ещё неявно класс создаёт.

vsb>А то так и до оператора "стрелочка" можно дойти:

Это уже синтаксическое издевательствао..
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Класс для возврата значения из лямбды
От: m2user  
Дата: 10.01.23 16:24
Оценка:
M>>https://www.baeldung.com/java-lambda-effectively-final-local-variables#instance-variables
·>volatile вообще не в тему.

В каком смысле не в тему? Там же пример как раз на многопоточный доступ к экземпляру класса.

·>Теперь нам надо как-то изобретать правила для неинициализированных значений на стеке и правила final initialized once (т.е. если у нас объявлен final int val)... А ещё и c.accept() может выполняться из другого треда и проблемы с happens-before...

·>Т.е. на пустом месте усложняем ЯП, делаем кучу особых случаев, неявных дейсвтий и/или вносим лишнюю пессимизацию неявной расстановкой volatile или синхронизации например.

Не совсем понял пример. Assert покажет, что то допущение, которое сделал первый программист относительно метода f неверно.
Но не важно. Я согласен, что неявный "пессимистический" volatile в принципе достаточен для того, чтобы понять мотивацию такого подхода к variable capturing.

·>В общем, я считаю, что в java сделали всё правильно — максимально осторожно и явно.


Раз они решили все делать максимально осторожно, то почему не требуют final или volatile при захвате instance variable?
Пример с baeldung.com, на который я уже ссылался ранее скомпилируется и без volatile.

private volatile boolean run = true;

public void instanceVariableMultithreading() {
    executor.execute(() -> {
        while (run) {
            // do operation
        }
    });

    run = false;
}
Re[7]: Класс для возврата значения из лямбды
От: · Великобритания  
Дата: 10.01.23 17:29
Оценка:
Здравствуйте, m2user, Вы писали:

M>>>https://www.baeldung.com/java-lambda-effectively-final-local-variables#instance-variables

M>·>volatile вообще не в тему.
M>В каком смысле не в тему? Там же пример как раз на многопоточный доступ к экземпляру класса.
Ну да. И это никак не связано с сабжем же.

M>·>Теперь нам надо как-то изобретать правила для неинициализированных значений на стеке и правила final initialized once (т.е. если у нас объявлен final int val)... А ещё и c.accept() может выполняться из другого треда и проблемы с happens-before...

M>·>Т.е. на пустом месте усложняем ЯП, делаем кучу особых случаев, неявных дейсвтий и/или вносим лишнюю пессимизацию неявной расстановкой volatile или синхронизации например.
M>Не совсем понял пример. Assert покажет, что то допущение, которое сделал первый программист относительно метода f неверно.
Именно. Поведение метода можно задокументировать и т.п. А если как ты предложил "компилятор будет генерировать временный класс" — то не очень ясно какой именно класс генерировать — с volatile или без? toString? hashCode? И главное зачем впендюривать такое в компилятор, ведь можно и на уровне библиотеки такой класс наваять, если очень хочется.

M>Но не важно. Я согласен, что неявный "пессимистический" volatile в принципе достаточен для того, чтобы понять мотивацию такого подхода к variable capturing.

Плюс неявный боксинг я ещё забыл упомянуть.

M>·>В общем, я считаю, что в java сделали всё правильно — максимально осторожно и явно.

M>Раз они решили все делать максимально осторожно, то почему не требуют final или volatile при захвате instance variable?
M>Пример с baeldung.com, на который я уже ссылался ранее скомпилируется и без volatile.
Не понял какие проблемы с захватом instance variable, я не вижу никаих тут проблем. Мы вроде говорили о захвате stack variable.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Класс для возврата значения из лямбды
От: m2user  
Дата: 11.01.23 18:09
Оценка:
M>>·>Теперь нам надо как-то изобретать правила для неинициализированных значений на стеке и правила final initialized once (т.е. если у нас объявлен final int val)... А ещё и c.accept() может выполняться из другого треда и проблемы с happens-before...
M>>·>Т.е. на пустом месте усложняем ЯП, делаем кучу особых случаев, неявных дейсвтий и/или вносим лишнюю пессимизацию неявной расстановкой volatile или синхронизации например.
M>>Не совсем понял пример. Assert покажет, что то допущение, которое сделал первый программист относительно метода f неверно.
·>Именно. Поведение метода можно задокументировать и т.п. А если как ты предложил "компилятор будет генерировать временный класс" — то не очень ясно какой именно класс генерировать — с volatile или без? toString? hashCode? И главное зачем впендюривать такое в компилятор, ведь можно и на уровне библиотеки такой класс наваять, если очень хочется.

Поведение компилятора тоже можно задокументировать.
Скажем так, в С# сделали захват локальных переменных в лямбды (правда почему-то плохо задокументировали возможные побочные эффекты связанные с многопоточностью и пр.), и не нужно ничего придумывть с Tuple/Records и пр., что уже было предложено в этой теме ранее.
Re[9]: Класс для возврата значения из лямбды
От: · Великобритания  
Дата: 11.01.23 21:38
Оценка:
Здравствуйте, m2user, Вы писали:

M>>>Не совсем понял пример. Assert покажет, что то допущение, которое сделал первый программист относительно метода f неверно.

M>·>Именно. Поведение метода можно задокументировать и т.п. А если как ты предложил "компилятор будет генерировать временный класс" — то не очень ясно какой именно класс генерировать — с volatile или без? toString? hashCode? И главное зачем впендюривать такое в компилятор, ведь можно и на уровне библиотеки такой класс наваять, если очень хочется.
M>Поведение компилятора тоже можно задокументировать.
Можно. Но это уже будет компилятор, который должен давать интуитивно понятный код.

M>Скажем так, в С# сделали захват локальных переменных в лямбды (правда почему-то плохо задокументировали возможные побочные эффекты связанные с многопоточностью и пр.),

В шарпе довольно мерзкая грабля с этим: https://stackoverflow.com/questions/4155691/c-sharp-lambda-local-variable-value-not-taken-when-you-think
А в java же код очень однозначно понимается. Зачем компилятору генерировать код, если этот код и так тривиально пишется, притом с нужными эффектами|многопоточкой и т.п. как надо по месту, а не как отлито в граните стандарта яп.

M>и не нужно ничего придумывть с Tuple/Records и пр., что уже было предложено в этой теме ранее.

В данном случае гораздо лучше анонимные типы, как я предложил, имхо.
А лямбды и не помогают написать красивый код в данном случае, ибо переменые не константны, а значит можно присвоить несколько раз или совсем не присвоить.
List<Employee> employees = null;//вот зачем тут в null надо? Приходится специальное значение для неинициализированных переменных придумывать
List<Appointment> appointments = null;
execute(() => {
  employees = query(...);
  if(...) {
    appointments = query(...);
  }
};

В общем в век иммутабельности такое в топку.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.