Легкий оценочный/прикладной порядок и ленивая оценка/нормальный порядок
Насколько я знаю, нетерпеливый оценочный/прикладной порядок оценивает все аргументы функции перед его применением, с другой стороны, ленивая оценка/нормальный порядок оценивает аргументы только тогда, когда это необходимо.
Итак, каковы различия между парой терминов с нетерпением и аппликативным порядком, ленивой оценкой и нормальным порядком?
Спасибо.
Ответы
Ответ 1
Ленивая оценка оценивает срок не более одного раза, в то время как нормальный порядок будет оценивать его так часто, как кажется. Например, если у вас есть f(x) = x+x
, и вы называете его f(g(42))
, тогда g(42)
вызывается один раз под ленивой оценкой или аппликативным порядком, но дважды в обычном порядке.
Удовлетворяющая оценка и аппликативный порядок являются синонимами, по крайней мере, при использовании определения прикладного порядка, содержащегося в "Структура и интерпретация компьютерных программ", которое, по-видимому, соответствует вашим требованиям. (Wikipedia определяет прикладной порядок немного по-другому и имеет его как особый случай нетерпеливой оценки).
Ответ 2
Я тоже читаю SICP, и мне было любопытно определение нормального порядка, данное авторами. Мне показалось, что это похоже на оценку Lazy, поэтому я пошел искать дополнительную информацию относительно обоих.
Я знаю, что этот вопрос был задан давно, но я просмотрел FAQ и не нашел упоминания о ответах на старые вопросы, поэтому я подумал, что оставлю то, что нашел здесь, чтобы другие люди могли использовать его в будущее.
Это то, что я нашел, и я склонен согласиться с ними:
Я бы поспорил (как и другие), что ленивая оценка и NormalOrderEvaluation - это две разные вещи; разница упомянутый выше. В ленивой оценке оценка аргумента отложенных до тех пор, пока это не понадобится, и в этот момент аргумент оценивается и его результат сохранен (memoized). Дальнейшее использование аргумента в функция использует вычисленное значение. Операторы C/С++ ||, & &, и?: оба являются примерами ленивой оценки. (Если только некоторые новички C/С++ программист достаточно глубже, чтобы перегружать && & & или ||, и в этом случае перегруженные версии оцениваются в строгом порядке; поэтому & & и || операторы НИКОГДА не будут перегружены в С++).
Другими словами, каждый аргумент оценивается не более одного раза, возможно, не на всех.
NormalOrderEvaluation, с другой стороны, переоценивает выражение каждый раз, когда он используется. Подумайте о макросах C, CallByName на языках, которые поддерживать его и семантику циклов управления структурами и т.д. Оценка нормального порядка может занять гораздо больше времени, чем аппликативный порядок оценки и может вызывать побочные эффекты более одного раза. (Вот почему, конечно, заявления с побочными эффектами обычно должны не указываются в качестве аргументов для макросов в C/С++)
Если аргумент инвариантен и не имеет побочных эффектов, единственное разница между ними - производительность. Действительно, чисто функциональный язык, ленивый eval можно рассматривать как оптимизацию оценка нормального порядка. При наличии побочных эффектов или выражений которые могут возвращать другое значение при переоценке, эти два имеют различное поведение; нормальный порядок eval, в частности, имеет плохую репутация в процедурных языках из-за сложности рассуждений о таких программах без ReferentialTransparency
Следует также отметить, что оценка строгого порядка (а также ленивая оценка) может быть достигнута на языке, который поддерживает нормальный порядок с помощью явного замещения. Противоположность неверна; это требует передача в куски, функции или объекты, которые могут быть вызваны/переданы чтобы отложить/повторить оценку.
и
Ленивая оценка объединяет оценку и обмен нормального порядка:
• Никогда не оценивайте что-либо, пока не получится (нормальный порядок)
• Никогда не оценивайте что-то более одного раза (общий доступ)
http://c2.com/cgi/wiki?LazyEvaluation
http://cs.anu.edu.au/student/comp3610/lectures/Lazy.pdf