Здравствуйте, Shmj, Вы писали:
S>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует.
В какой-то части можно но нахрена?
Здравствуйте, GarryIV, Вы писали:
S>>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует. GIV>В какой-то части можно но нахрена?
Для чистоты кода, конечно же. Один раз забыл написать await, а оно даже не предупредило. Даже не один раз.
А вот кода nowait — это явно не забудешь, т.к. из ряда вон выходящее.
Здравствуйте, Shmj, Вы писали:
S>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует. S>Получается если не нужно ждать результата функции — пишем наоборот — nowait. Если ждать результат — ничего не пишем, по умолчанию.
Ты, кажется, хотел сказать наоборот. nowait как раз вообще ничего не требует за пределами обычной парадигмы даже без async/await, это возврат к тому, что было до них. Запросил асинхронную операцию и потом ждёшь нотификации, и все проблемы в том, как именно организовать максимально эффективное и при этом удобное ожидание.
То есть тут ничего нового.
А если таки весь код как бы async, но при этом можно явно ставить ожидание — то это Erlang или Go, или вообще что угодно на зелёных нитках.
Здравствуйте, netch80, Вы писали:
N>Ты, кажется, хотел сказать наоборот. nowait как раз вообще ничего не требует за пределами обычной парадигмы даже без async/await, это возврат к тому, что было до них.
Требует — это отказ от ожидания пока исполнится асинхронная операция.
Здравствуйте, Shmj, Вы писали:
S>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует.
Кроме эрланга посмотри еще на голанг и хаскель!
А вообще, асинхронные вычисления удобно рассматривать в контексте монад как частный случай. Концептуально так проще и понятнее становится (если знаком с монадами)
Здравствуйте, SkyDance, Вы писали:
SD>Можно просто использовать язык, где эти костыли не нужны. Например, Erlang — там подобной дури нет и в помине.
В Erlang разве не обычные синхронные функции, обертывание которых в процессы требует даже большей церемонии чем async/await в C#/JS/Python?
Здравствуйте, Shmj, Вы писали:
S>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует. S>Т.к. в основном асинхронных больше и даже если какая не асинхронная — то компилятор мог бы сам оптимизировать.
В GoLang сделано близко — "горутинность" запихана в вызов, а не в декларацию функции. Другое дело, что разница все равно прошита в самом коде (return vs channels), то есть бестолково чуть менее чем полностью.
Здравствуйте, novitk, Вы писали:
N>В GoLang сделано близко — "горутинность" запихана в вызов, а не в декларацию функции. Другое дело, что разница все равно прошита в самом коде (return vs channels), то есть бестолково чуть менее чем полностью.
На практике "не ждать" нужно очень-очень редко, раз в год можно и канал написать в хитром случае. А по факту весь код в го чистый без async/await мусора и по умолчанию асинхронный.
Здравствуйте, mrTwister, Вы писали:
T>На практике "не ждать" нужно очень-очень редко, раз в год можно и канал написать в хитром случае.
Ровно как и в C#/JS/Python. 99% вызовов функций идет в режиме "ждать". Поэтому эта идея ТС плохая:
Получается если не нужно ждать результата функции — пишем наоборот — nowait. Если ждать результат — ничего не пишем, по умолчанию.
T>А по факту весь код в го чистый без async/await мусора и по умолчанию асинхронный.
Религией попахивает. "Еxplicit is better then implicit", как мы знаем.
Здравствуйте, novitk, Вы писали:
N>Здравствуйте, mrTwister, Вы писали:
T>>На практике "не ждать" нужно очень-очень редко, раз в год можно и канал написать в хитром случае. N>Ровно как и в C#/JS/Python. 99% вызовов функций идет в режиме "ждать". Поэтому эта идея ТС плохая: N>
N>Получается если не нужно ждать результата функции — пишем наоборот — nowait. Если ждать результат — ничего не пишем, по умолчанию.
Только в C# и пр. есть два вида "ждать": можно ждать синхронно, а можно ждать асинхронно. Причем синхронное ожидание внешне никак не отличается от "не ждать". Это разделение не только замусоривает и заставляет делать два варианта функций, но и очень часто приводит к ошибкам, когда внутри асинхронной функции случайно вызвали сихронное ожидание. Хуже всего, что оно даже будет корректно работать, но под нагрузкой выжрет все треды в пуле и приложение встанет колом
T>>А по факту весь код в го чистый без async/await мусора и по умолчанию асинхронный. N>Религией попахивает. "Еxplicit is better then implicit", как мы знаем.
Все максимально explicit:
foo() — ждем
go foo() — не ждем
Здравствуйте, mrTwister, Вы писали:
T>Только в C# и пр. есть два вида "ждать": можно ждать синхронно, а можно ждать асинхронно. Причем синхронное ожидание внешне никак не отличается от "не ждать"...., но и очень часто приводит к ошибкам, когда внутри асинхронной функции случайно вызвали сихронное ожидание.
Как это не отличается и какие нафиг ошибки?! Там тип результата разный (Task<T> vs T). Компилятор сразу по рукам.
T>Все максимально explicit: T>foo() — ждем T>go foo() — не ждем T>
T>Все, больше вариантов нет
Речь об explicit в описание функции, а не в вызове. В обеих языках функцию из "ждем" в "не ждем" надо переписывать. Можно даже сказать, что в C# ee переписывать проще, так как каналы это лишние церемонии и в 99% случаев сингулярного результата достаточно.
Здравствуйте, novitk, Вы писали:
N>Здравствуйте, mrTwister, Вы писали:
T>>Только в C# и пр. есть два вида "ждать": можно ждать синхронно, а можно ждать асинхронно. Причем синхронное ожидание внешне никак не отличается от "не ждать"...., но и очень часто приводит к ошибкам, когда внутри асинхронной функции случайно вызвали сихронное ожидание. N>Как это не отличается и какие нафиг ошибки?! Там тип результата разный (Task<T> vs T). Компилятор сразу по рукам.
Декларация функций разная, но вызов при этом выглядит одинаково: foo()
T>>Все максимально explicit: T>>foo() — ждем T>>go foo() — не ждем T>>
T>>Все, больше вариантов нет N>Речь об explicit в описание функции, а не в вызове. В обеих языках функцию из "ждем" в "не ждем" надо переписывать. Можно даже сказать, что в C# ee переписывать проще, так как каналы это лишние церемонии и в 99% случаев сингулярного результата достаточно.
В go ничего переписывать не надо, функция всегда выглядит одинаково. Если клиенту почему-то надо запускать функцию в горутине, он сам ее и запускает. Функции все равно где ее запускает, она асинхронная с самого начала. А вот в C# функцию придется переписать. Причем не просто её переписать, но еще и переписать все функции, которые она вызывает и так далее. Если есть цепочка вызовов Foo->Bar->Baz->ReadFile, и понадобилась асинхронная версия Foo, то придется переписать все функции из этой цепочки вызовов: AsyncFoo->AsyncBar->AsyncBaz->AsyncReadFile. В go ничего не надо переписывать.
Здравствуйте, mrTwister, Вы писали:
T>В go ничего переписывать не надо, функция всегда выглядит одинаково.
Ты повторяешь одно и тоже. Вместо формализма, что функции в Го не помечены, с которого я собственно и начал, приведи пример реальной функции в go которая бы работала в двух контекстах?
N>В Erlang разве не обычные синхронные функции, обертывание которых в процессы требует даже большей церемонии чем async/await в C#/JS/Python?
Не знаю, что подразумевается под "церемониями", но там все реально очень просто, в том числе и запуск отдельного процесса. Там всего лишь правильно представлен нужный примитив — `receive`. Поэтому код действительно выглядит как "обычные синхронные функции", которые ты можешь запускать в своем процессе, или в отдельном, и когда тебе требуется результат — делать оный receive. Благодаря pattern matching код выглядит ну очень элегантно. А главное, легко читать и понимать. К тому же call stack нормальный, а не как с C#
Здравствуйте, SkyDance, Вы писали:
SD>церемониями", но там все реально очень просто, в том числе и запуск отдельного процесса. Там всего лишь правильно представлен нужный примитив — `receive`. Поэтому код действительно выглядит как "обычные синхронные функции", которые ты можешь запускать в своем процессе, или в отдельном, и когда тебе требуется результат — делать оный receive. Благодаря pattern matching код выглядит ну очень элегантно. А главное, легко читать и понимать. К тому же call stack нормальный, а не как с C#
Написать go вместо async и receive вместо await делает код легкочитабельным?