Где умные применения строгой оценки?

Кажется, есть много примеров того, как умные вещи делаются на языке с ленивой оценкой, что невозможно сделать в среде со строгой оценкой. Например, бесконечные списки в Haskell или замена каждого элемента в дереве на минимальное значение дерева за один проход.

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


person drt    schedule 16.03.2009    source источник
comment
Помимо теории, в ленивых языках могут быть хитрые способы применения строгой оценки. В Haskell есть! аннотация строгости для типов данных для использования при принудительной оценке терминов, для которых ленивость вызвала бы только раздувание памяти. Хорошими примерами того, когда нужно выключить лень, несомненно, будет разумное использование строгой оценки.   -  person rndmcnlly    schedule 05.05.2009


Ответы (9)


Основные вещи, которые вы можете легко сделать на нетерпеливом (строгом) языке, а не на ленивом:

  • Прогнозируйте из исходного кода временные и пространственные затраты ваших программ.

  • Разрешить побочные эффекты, включая обновление изменяемых массивов в постоянное время, что упрощает быструю реализацию некоторых алгоритмов.

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

При этом в целом я предпочитаю писать сложные вещи на Haskell.

person Norman Ramsey    schedule 20.03.2009

Нет; есть некоторые вещи, которые вы можете делать * с ленивым вычислением (AKA сокращение нормального порядка или крайнее левое сокращение), которые вы не можете сделать при строгом вычислении, но не наоборот.

Причина этого в том, что ленивое вычисление в некотором роде является «самым общим» способом оценки, который известен как:

Теорема вычислительной адекватности: если некоторый порядок оценки завершается и дает определенный результат, то ленивое вычисление также прекращается и дает тот же результат.

* (обратите внимание, что мы не говорим об эквивалентности по Тьюрингу здесь)

person porges    schedule 17.03.2009
comment
Несмотря на то, что ваше утверждение было оценено как лучший ответ, ваше утверждение неверно, см. Мой ответ ниже. - person Ingo; 08.04.2009

Ну нет, более-менее по определению. На языке ленивого оценивания вы должны по определению получить те же результаты, что и при энергичном (действительно ли люди сейчас используют "строгий" анализ?), кроме для задержка оценки до тех пор, пока она не понадобится, последствия для хранения и все такое. Так что, если бы вы могли получить другое поведение кроме для этого, это было бы ошибкой.

person Charlie Martin    schedule 16.03.2009
comment
На самом деле семантика лени несколько отличается от строгости. Например, в строгом языке const 1 undefined имеет значение undefined, но на ленивом языке он оценивается как 1. Причина в том, что строгий язык оценивает undefined, а ленивый язык - нет. - person Paul Johnson; 17.03.2009

Наиболее очевидное использование лени в повседневном языке - это оператор «if», в котором выполняется только одна ветвь условного оператора.

Противоположностью чисто нестрогого (ленивого) языка был бы чисто строгий язык.

Существует по крайней мере один случай, когда «чисто строгий» полезен, а именно предикация ветки.

Примерный пересказ связанной статьи:

Давным-давно в мире процессоров инструкции для выполнения загружались, когда проверялось условие перехода. В какой-то момент были добавлены конвейеры команд, чтобы сократить время загрузки. Обратной стороной было то, что ЦП не знал, какую ветвь нужно загрузить, поэтому по умолчанию загружал одну. Если бы ветвь пошла в обратном направлении, конвейер остановился бы, пока был загружен код для другой ветки.

Решение состоит в том, чтобы загрузить обе ветки, выполнить обе ветки, а затем результат условного выражения скажет вам, какой результат ветки сохранить, а какой выбросить. Тогда вы не получите остановок на трубопроводе.

Это мой любимый (единственный?) Пример преимущества чисто строгого языка.

person shapr    schedule 11.05.2009

На ум приходят программы "Hello, World" или вообще все, что связано с побочными эффектами.

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

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

person Zorf    schedule 09.06.2010

Как Чарли Мартин написал, результат строгой и ленивой программы должен быть эквивалентным. Разница заключалась в ограничениях времени и пространства и / или в языковой выразительности. Помимо эффекта лени для ненужных значений, в ленивом языке можно легко вводить новые языковые конструкции без дополнительных языковых концепций (например, макрос в LISP). В любом случае, лень может вас укусить Как работает хвостовая рекурсия Haskell? и то же самое можно сказать. сложнее, чем на строгом языке. (Разве компилятор haskell не должен понимать, что compute +1 дешевле, чем make thunk ( x + 1 )?)

person Hynek -Pichi- Vychodil    schedule 16.03.2009

В языке строгой оценки, таком как C #, можно добиться ленивой оценки, возвращая преобразователь значения (Func) вместо самого значения. В качестве примера построение Y-комбинатора в C # можно сделать так:

public Func<int, int> Y(Func<Func<int, int>, Func<int, int>> f)
{
    return x => f(Y(f))(x);
}

Это объявление было бы более лаконичным в ленивой среде:

Y f = f (Y f)
person eulerfx    schedule 16.03.2009
comment
Это не относится к вашему примеру Y-Combinator, но в качестве примечания: чтобы получить оценку по запросу (как в Haskell) в C #, следует использовать Lazy<T>, а не Func<T> (последний будет пересчитывать значение каждый раз, когда оно используется). - person FunctorSalad; 08.06.2012

Я немного программирую на Erlang и считаю, что отсутствие ленивых оценок, которым я научился еще в университете, меня очень расстраивает.

Я вкратце рассмотрел некоторые проблемы Эйлера проекта, особенно те, которые имеют дело с простыми числами.

С ленивым вычислением у вас может быть функция, которая возвращает список всех простых чисел, но на самом деле возвращает только те, которые вам действительно нужны. Следовательно, очень легко сказать «дайте мне первые n простых чисел».

Без ленивых вычислений вы, как правило, получаете более ограничительный вариант «дайте мне список всех простых чисел от 1 до n».

person Alnitak    schedule 17.03.2009

Ответ, который был оценен как лучший, к сожалению, имеет логическую ошибку. Из теоремы, которую цитирует Поргес, не следует, что на ленивом языке можно сделать больше.

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

person Ingo    schedule 08.04.2009
comment
Это эквивалент Тьюринга ... Спрашивающий спросил, есть ли какие-нибудь «изящные уловки», которые можно сделать с помощью строгого языка, чего нельзя сделать с помощью ленивого; эта теорема говорит «нет», потому что ленивое вычисление является наиболее общим порядком вычисления. (Если мы посмотрим на это просто с точки зрения порядка уменьшения.) - person porges; 10.04.2009
comment
Я, конечно, согласен, но вы заявили, что есть некоторые вещи, которые вы можете делать * с ленивой оценкой ... чего вы не можете делать со строгой оценкой. Что остается ложью. Конечно, использовать отложенный список проще, скажем, в Haskell, чем в Java, но вопрос не в этом. - person Ingo; 11.04.2009