Здравствуйте, dilmah, Вы писали:
А>>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
D>практическая польза в том, что ты можешь писать более простой и понятный код, не волнуясь об оптимизации, зная что она произойдет автоматически.
Уж никак не более просто и понятный, ибо явная инициализация всегда на порядок проще и понятнее, чем ленивая, которая произойдёт непонятно когда, в каком потоке, и непонятно к чему приведёт при возникновении какого либо исключения
Здравствуйте, Аноним, Вы писали:
А>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
Примера из объектов реального мира я ещё не видел. Лично сам считаю что в 99% случаев ленивые вычисления являются проблемой дизайна.
Сами же ленивые вычисления только добавляют сложности в проекте ибо:
1. Не известен момент в который будет произведено вычисление
2. Не известен поток
3. Не известен call stack
4. При возникновении ошибки невозможно предсказать поведение системы
Ну и KISS ленивые вычисления явно нарушают.
В общем если вдруг вам нужны ленивые вычисления — нужно 10 раз подумать почему. Почему вы не можете явно их выполнить в вполне детерминированные момент времени.
Здравствуйте, Аноним, Вы писали:
А>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
Есть случаи, когда стратегия редукции «сначала самый глубокий редекс» приводит к бесконечным вычислениям. В то же время (если терм вообще сводится к терму в нормальной форме), стратегия «сначала самый внешний (левый) редекс» всегда завершается.
Классическим примером в нетипизированном лямбда-исчислении является применение функции x ↦ 1 к выражению (x ↦ x(x))(x ↦ x(x)).
Здравствуйте, Аноним, Вы писали:
А>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
Например, где сложный объект состоит из маленьких, но все они не нужны сразу. Типа Settings, которые могут содержать габариты окна "About" (для восстановления), но которые (габариты) читаются раз в сто лет — их отложенная загрузка поможет быстрее стартовать приложение.
Или там, где есть вероятность отброса результата (в играх).
Здравствуйте, Аноним, Вы писали:
А>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
я делал ленивую аллокацию памяти. был набо функций типа foo(HANDLE *h, ...), которым _иногда_ требовался буфер памяти, упрятанный в HANDLE, но чаще всего он просто болтался без дела. по спецификации буфер должен быть выделен и иницилизирован внутри INIT(HANDLE *h), но реально буфер выделялся только когда в нем возникала необходимость. причем такая имплементация спецификации не противоречила, но здорово экономила память в ситуации когда у нас много HANDLE (а их было реально много), но только некоторым из них нужен буфер.
так же ленивую загрузку внешних модулей делал. функция load_module(char *module_name) подгружала модуль только в момент превого вызова функции из него. плюс там еще была предусмотрена возможность фоновой загрузки, когда ЦП бездействует -- тогда на основе предшествующих запусков делались предсказания какие модули будут загружены и они грузились, когда юзер ничего не делает. в частности, модуль печати. грузить его сразу -- плохо, т.к. не факт, что он нужен. грузить его при первом вызове -- тормоза при нажатии на CTRL-P, нервирующие юзера. грузить его в фоне -- наименьшее зло ИМХО.
Здравствуйте, Tom, Вы писали:
Tom>Здравствуйте, Аноним, Вы писали:
А>>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление. Tom>Примера из объектов реального мира я ещё не видел. Лично сам считаю что в 99% случаев ленивые вычисления являются проблемой дизайна.
Tom>Сами же ленивые вычисления только добавляют сложности в проекте ибо: Tom>1. Не известен момент в который будет произведено вычисление
Зачем? Оно ведь может быть и не произведено.
Tom>2. Не известен поток Tom>3. Не известен call stack
Более того, ленивое вычисление может вообще не процессором выполняться.
Tom>4. При возникновении ошибки невозможно предсказать поведение системы
При отсутствии сайд-эффектов с точки зрения программы предсказать поведение вполне можно, так как ошибка может быть выкинута по месту обращения.
Tom>Ну и KISS ленивые вычисления явно нарушают.
Как раз наоборот. См аппликативный и нормальный порядок редукции.
Tom>В общем если вдруг вам нужны ленивые вычисления — нужно 10 раз подумать почему. Почему вы не можете явно их выполнить в вполне детерминированные момент времени.
Я бы сказал наоборот. Лучше использовать ленивые, пока вам однозначно не станут нужны энергичные вычисления.
Есть целых три НО:
1)Должна быть поддержка языка для ленивых вычислений (в C# её фактически нет), кроме Linq
2)Должны отсутствовать наблюдаемые сайд-эффекты в вычислениях
3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз
В C# всех трех условий нету, поэтому к ленивости надо относиться осторожно.
Здравствуйте, gandjustas, Вы писали:
G>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз
"Должна быть" и для итераторов?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, gandjustas, Вы писали:
G>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз
_FR>"Должна быть" и для итераторов?
У них по идее есть Reset(), правда не помню чтобы им когда-либо пользовались...
Здравствуйте, hardcase, Вы писали:
G>>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз _FR>>"Должна быть" и для итераторов? H>У них по идее есть Reset(), правда не помню чтобы им когда-либо пользовались...
Если мне не изменяет склероз, то Reset() из реализации ленивых итераторов делают throw new NotSupportedException(); Да и не имеют никакого отношения к запоминанию: скорее, к забыванию
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Аноним, Вы писали:
А>Приведите пожалуйста пример в каком практическом случае эффективно использовать ленивое вычисление.
В плане производительности полезны, если нужны тяжелые промежуточные объекты. Ленивость в таких задачах позволяет получить приличный выигрыш по пиковой памяти и существенный в производительности (десятки процентов). Но если промежуточные объекты легкие, тогда смысла использовать ленивость нет, производительность обычно наоборот хуже.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, gandjustas, Вы писали:
G>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз
_FR>"Должна быть" и для итераторов?
Итераторы как раз обладают наблюдаемыми побочными эффектами, так что ленивости для них быть не должно в принципе.
Здравствуйте, gandjustas, Вы писали:
G>>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз _FR>>"Должна быть" и для итераторов? G>Итераторы как раз обладают наблюдаемыми побочными эффектами, так что ленивости для них быть не должно в принципе.
То есть и yield return "не должно быть в принципе"?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, gandjustas, Вы писали:
G>>>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз _FR>>>"Должна быть" и для итераторов? G>>Итераторы как раз обладают наблюдаемыми побочными эффектами, так что ленивости для них быть не должно в принципе.
_FR>То есть и yield return "не должно быть в принципе"?
Как с yield никаких проблем нету. yield сам по себе никаких побочных эффектов не имеет. а вот использование IEnumerator еще как имеет.
Здравствуйте, gandjustas, Вы писали:
G>>>>>3)Ленивость должна быть с запоминанием, те если ленивое выражение было вычислено, но оно не должно вычисляться второй раз _FR>>>>"Должна быть" и для итераторов? G>>>Итераторы как раз обладают наблюдаемыми побочными эффектами, так что ленивости для них быть не должно в принципе. _FR>>То есть и yield return "не должно быть в принципе"?
G>Как с yield никаких проблем нету. yield сам по себе никаких побочных эффектов не имеет. а вот использование IEnumerator еще как имеет.
Не понял yield же создаёт ни что иное, как нечто ленивое. Причем "без запоминания". Почему же "нету проблем"?
И в чём смысл разделять yield и IEnumerator?
static IEnumerator M() {
yield return 1;
}
Может, имеет смысл описать подробнее, какие проблемы даёт "использование IEnumerator" при том, что "с yield никаких проблем нету"?
Help will always be given at Hogwarts to those who ask for it.