Я часто читал, что ленивый не совпадает с нестрогим, но мне трудно понять разницу. Они, кажется, используются взаимозаменяемо, но я понимаю, что они имеют разные значения. Я был бы признателен за помощь в понимании разницы.
У меня есть несколько вопросов, которые разбросаны по этому сообщению. В конце этой публикации я обобщу эти вопросы. У меня есть несколько примеров фрагментов, я их не тестировал, я только представил их как понятия. Я добавил цитаты, чтобы спасти вас от поиска их. Возможно, это поможет кому-то позже с тем же вопросом.
Нелинейная защита:
Функция f называется строгой, если при применении к бесконечному выражение также не может завершиться. Другими словами, f строго если значение f bot равно |. Для большинства языков программирования все функции строгие. Но это не так в Haskell. Как простой Например, рассмотрим const1, функцию константы 1, определяемую:
const1 x = 1
Значение const1 бота в Haskell равно 1. Оперативно, так как const1 не "нуждается" в значении его аргумента, он никогда не пытается оценивать его и, таким образом, никогда не попадает в нескончаемый вычисление. По этой причине нестрогие функции также называются "ленивые функции", и, как говорят, оценивают их аргументы "лениво", или "по необходимости".
- Нежное введение в Haskell: функции
Мне очень нравится это определение. Кажется, это лучшее, что я мог найти для понимания строгих. Является ли const1 x = 1
ленивым?
Не строгость означает, что редукция (математический термин для оценка) поступает извне,
так что если у вас есть (a + (bc)), тогда сначала вы уменьшаете +, затем уменьшаете внутренний (bc).
- Haskell Wiki: Lavy vs non-strict
Haskell Wiki действительно меня смущает. Я понимаю, что они говорят о порядке, но я не вижу, как (a+(b*c))
будет оценивать нестрого, если бы это было pass _|_
?
В нестрогой оценке аргументы функции не вычисляются если они фактически не используются при оценке тела функции.
При кодировании Церкви ленивая оценка карт операторов нестандартной оценка функций; по этой причине нестрогая оценка часто называемый "ленивым". Булевы выражения на многих языках используют форма нестрогой оценки называется оценкой короткого замыкания, где оценка возвращается, как только можно определить, что однозначная Булев результат - например, в дизъюнктивном выражении, где true, или в конъюнктивном выражении, где false столкнулись и т.д. Условные выражения также обычно используют ленивая оценка, когда оценка возвращается, как только однозначная ветвь.
Lazy Def:
С другой стороны, ленивая оценка означает только оценку выражение, когда его результаты необходимы (обратите внимание на переход от "сокращение" до "оценки" ). Поэтому, когда механизм оценки видит выражение создает строчную структуру данных, содержащую любые значения необходимы для оценки выражения, а также указатель на само выражение. Когда результат действительно необходим, оценка движок вызывает выражение, а затем заменяет thunk результат для дальнейшего использования....
Очевидно, существует сильное соответствие между thunk и частично оцененное выражение. Следовательно, в большинстве случаев термины "ленивые" и "нестрогие" - синонимы. Но не совсем.
- Haskell Wiki: Lavy vs non-strict
Это похоже на конкретный ответ Хаскелла. Я считаю, что ленивый означает, что thunks и нестрогий означает частичную оценку. Это слишком упрощенное сравнение? ленивый всегда означает, что thunks и нестрогий всегда означают частичную оценку.
В теории языка программирования ленивая оценка или по требованию 1является стратегия оценки, которая задерживает оценку выражения до тех пор, пока его значение не будет действительно необходимым (нестрогая оценка), а также избегать повторных оценок (совместного использования).
Императивные примеры
Я знаю, что большинство людей говорят о необходимости забыть о программировании при изучении функционального языка. Тем не менее, я хотел бы знать, если они квалифицируются как нестрогие, ленивые, оба или никоим образом? По крайней мере, это обеспечило бы что-то знакомое.
Короткое замыкание
f1() || f2()
С#, Python и другие языки с "yield"
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
Callbacks
int f1() { return 1;}
int f2() { return 2;}
int lazy(int (*cb1)(), int (*cb2)() , int x) {
if (x == 0)
return cb1();
else
return cb2();
}
int eager(int e1, int e2, int x) {
if (x == 0)
return e1;
else
return e2;
}
lazy(f1, f2, x);
eager(f1(), f2(), x);
Вопросы
Я знаю, что ответ прямо передо мной со всеми этими ресурсами, но я не могу его понять. Все кажется, что определение слишком легко отклонено как подразумеваемое или очевидное.
Я знаю, что у меня много вопросов. Не стесняйтесь отвечать на любые вопросы, которые вы считаете актуальными. Я добавил эти вопросы для обсуждения.
- Является ли
const1 x = 1
ленивым? - Как оценивается "внутреннее" не строгое? Это потому, что внутрь позволяет уменьшить ненужные выражения, например, в
const1 x = 1
? Сокращения, похоже, соответствуют определению ленивого. - Значит ли ленивый thunks и нестрогий всегда означает частичную оценку? Это просто обобщение?
- Являются ли следующие императивные понятия "ленивыми", "не строгими", "оба" или "нет"?
- Короткое замыкание
- Использование yield
- Передача обратных вызовов для задержки или предотвращения выполнения
- Является ленивым подмножеством нестрогим или наоборот, или они являются взаимоисключающими. Например, возможно ли быть нестрогим, не будучи ленивым или ленивым, не будучи нестрогим?
- Не строгость Хаскелла достигается лень?
Спасибо вам!