Size: a a a

2020 March 05

P

Pavel in rust_offtopic
λоλторт
Очень легко понаблюдать "нечистоту" просто заменяя в одни таски на функции из юнита, а другие не заменяя
таска это объект, хз что ты там пронаблюдаешь
источник

P

Pavel in rust_offtopic
пока не отправишь на экзекутор будет просто мёртвый код
источник

DS

Doge Shibu in rust_offtopic
Pavel
ну и допустим я получил файл по сети и захотел часть его отправить в бекап, а часть -- распарсить и записать в базу, чтоб размазать нагрузку на сеть я хочу начать бекап сразу, а не делать его одновременно с записью в базу, чтоб не держать долго транзакцию через медленную сеть
Запросто, для этого у ленивых тасок есть свои комбинаторы, чтобы получить подобное поведение:

IO.parallel(writeToBackupStorage(file), writeToDb(file))

И тогда эти задачи запустятся параллельно.
источник

λ

λоλторт in rust_offtopic
Doge Shibu
Запросто, для этого у ленивых тасок есть свои комбинаторы, чтобы получить подобное поведение:

IO.parallel(writeToBackupStorage(file), writeToDb(file))

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

P

Pavel in rust_offtopic
Doge Shibu
Запросто, для этого у ленивых тасок есть свои комбинаторы, чтобы получить подобное поведение:

IO.parallel(writeToBackupStorage(file), writeToDb(file))

И тогда эти задачи запустятся параллельно.
ну а я пишу  CompletableFuture.allOf(backupFuture, parseFuture.andThen(this::writeToDb))
источник

DS

Doge Shibu in rust_offtopic
λоλторт
И эти комбинаторы, намного удобнее и прозрачнее всего что есть у фьюч
Скорее они явнее отражают семантику желаемых действий.
источник

P

Pavel in rust_offtopic
Pavel
ну а я пишу  CompletableFuture.allOf(backupFuture, parseFuture.andThen(this::writeToDb))
при том, что исполнение уже началось
источник

DS

Doge Shibu in rust_offtopic
Pavel
ну а я пишу  CompletableFuture.allOf(backupFuture, parseFuture.andThen(this::writeToDb))
Ну разница в том, что ты небольшими правками и рефакторингами как на картинке выше не поменяешь желаемое тобой поведение у программы с ленивыми тасками.

Рефакторить проще и удобнее будет.
источник

DS

Doge Shibu in rust_offtopic
Не надо будет мозг включать, что важно
источник

P

Pavel in rust_offtopic
Doge Shibu
Ну разница в том, что ты небольшими правками и рефакторингами как на картинке выше не поменяешь желаемое тобой поведение у программы с ленивыми тасками.

Рефакторить проще и удобнее будет.
не понимаю почему
источник

P

Pavel in rust_offtopic
мб я просто лучше не видел, но тебе всё равно надо будет дождаться исполнения всех, чтоб получить результат + зависимости не дропнешь, если есть зависимости -- просто комбинируешь сами лямбды в фьюче
источник

P

Pavel in rust_offtopic
тоесть ты можешь явно синхронно вызвать код, а можешь просто скомбинировать его с фьючей, я не понимаю зачем здесь ленивость
источник

DS

Doge Shibu in rust_offtopic
Pavel
не понимаю почему
Опять-таки, пример выше.

У тебя есть какой-то
def compute() = { print("BOOM"); 123 }

val fa = Future(compute())
val fb = Future(compute())

for(a <- fa; b <- fb) yield a + b

// Хочу отрефакторить

val myCompute = Future(compute())

for(a <- myCompute; b <- myCompute) yield a + b

// получаю не то поведение, что было до этого
// теперь с ленивыми футурами:
// До
IO.parallel(LazyFuture(compute(), LazyFuture(compute())).map((a, b) => a + b)

// после рефакторинга
val myComputeLazy = LazyFuture(compute())

IO.parallel(myComputeLazy, myComputeLazy).map((a,b) => a + b)

// поведение будет сохраненно
в результате рефакторинга
источник

DS

Doge Shibu in rust_offtopic
То есть именно что рефакторинг можно сделать без необходимости думать, что повлечет за собой запуск Future, чисто механическим образом
источник

DS

Doge Shibu in rust_offtopic
Опять-таки ленивые футуры позволяют более эргономичные примитивы синхронизации использовать вроде Ref'ов, MVar'ов, ФП семафоров и короля их всех - STM и всякие TVar и т.п.
источник

P

Pavel in rust_offtopic
Doge Shibu
Опять-таки, пример выше.

У тебя есть какой-то
def compute() = { print("BOOM"); 123 }

val fa = Future(compute())
val fb = Future(compute())

for(a <- fa; b <- fb) yield a + b

// Хочу отрефакторить

val myCompute = Future(compute())

for(a <- myCompute; b <- myCompute) yield a + b

// получаю не то поведение, что было до этого
// теперь с ленивыми футурами:
// До
IO.parallel(LazyFuture(compute(), LazyFuture(compute())).map((a, b) => a + b)

// после рефакторинга
val myComputeLazy = LazyFuture(compute())

IO.parallel(myComputeLazy, myComputeLazy).map((a,b) => a + b)

// поведение будет сохраненно
в результате рефакторинга
мне просто странно, что у тебя два раза вызвалась фьюча делающая одно и то же, тем более без аргументов, единственный повод существования такого, как по мне -- чтение снаружи, поскольку мир вокруг может меняться, то мне кажется, что ленивая фьюча тут как раз сломает код
источник

AZ

Alex Zhukovsky in rust_offtopic
как вы за 3 часа стока наспамили
источник

P

Pavel in rust_offtopic
Alex Zhukovsky
как вы за 3 часа стока наспамили
IO
источник

DS

Doge Shibu in rust_offtopic
Pavel
мне просто странно, что у тебя два раза вызвалась фьюча делающая одно и то же, тем более без аргументов, единственный повод существования такого, как по мне -- чтение снаружи, поскольку мир вокруг может меняться, то мне кажется, что ленивая фьюча тут как раз сломает код
Чуть выправил примеры, чтобы было аналогичнее между ленивым и неленивым примерами
источник

P

Pavel in rust_offtopic
Doge Shibu
Чуть выправил примеры, чтобы было аналогичнее между ленивым и неленивым примерами
посмотрел ещё раз, не понял, чем отличается от не-ленивых
источник