Все последующие комментарии основаны на выборе стандартной стратегии реализации с использованием замыканий для представления значений функций и порядка оценки по вызовам:
Для чистого лямбда-исчисления сбор мусора не является необходимым. Это связано с тем, что невозможно сформировать циклы в куче: каждое вновь выделенное значение может содержать только ссылки на ранее выделенные значения, и поэтому граф памяти образует DAG - поэтому для управления памятью достаточно подсчета ссылок.
Большинство реализаций не используют подсчет ссылок по двум причинам.
- Они поддерживают форму указателя типа (например,
ref
конструктор типа в ML), и поэтому могут формироваться истинные циклы в куче.
- Подсчет ссылок гораздо менее эффективен, чем сборка мусора, так как
- это требует много дополнительного места для хранения счетчиков ссылок, и
- обновление счетчиков, как правило, тратится впустую, и
- Обновление счетчиков создает множество конфликтов записи, что убивает параллельную производительность.
Языки с линейной типизацией могут исключить счетчик ссылок (в основном потому, что счетчики равны 0-1: либо значение имеет единственную ссылку на него, либо оно мертвое и может быть освобождено).
Однако выделения стека все еще недостаточно. Это связано с тем, что можно формировать значения функций, которые ссылаются на свободные переменные (т. Е. Нам нужно реализовать замыкания функций), если вы размещаете вещи в стеке, то действующие значения могут чередоваться с мертвыми значениями, что приведет к неправильной асимптотике. использование пространства
Вы можете получить правильную асимптотику, заменив стек «стеком спагетти» (т. Е. Реализуйте этот стек как связанный список в куче, чтобы при необходимости можно было вырезать мертвые кадры).
Если вам нужна дисциплина реального стека, вы можете использовать системы типов, основанные на «упорядоченной логике» (по существу, линейные типы за вычетом обмена).