Замыкания и динамический охват?
Я думаю, что понимаю, почему существует опасность в том, что допускается замыкание в языке с использованием динамического объема. То есть кажется, что вы сможете закрыть переменную OK, но при попытке прочитать ее вы получите только значение в верхней части глобального стека. Это может быть опасно, если другие функции используют то же имя в промежуточный период.
Я пропустил некоторые другие тонкости?
2 ответа
Да, это основная проблема. Термин "закрытие" сокращенно означает "лексическое закрытие", что по определению охватывает его лексическую сферу. Я бы назвал вещи в динамически ограниченном языке чем-то другим, например, LAMBDA
, Лямбды совершенно безопасны на динамически ограниченном языке, если вы не пытаетесь их вернуть.
(Для интересного мысленного эксперимента сравните проблему возврата лямбды с динамической областью в Emacs Lisp с проблемой возврата ссылки на переменную, выделенную в стеке, в C, и выясните, как и то, и другое невозможно в Scheme.)
Давным-давно, когда языки с динамической областью действия были намного реже, чем сегодня, это было известно как проблема funargs. Проблема, о которой вы говорите, - это проблема с восходящими фунгаргами.
Я понимаю, что на годы опаздываю, отвечая на этот вопрос, но я просто наткнулся на этот вопрос во время поиска в сети и хотел исправить некоторую дезинформацию, которая размещена здесь.
"Закрытие" означает просто вызываемый объект, который содержит как код, так и среду, которая обеспечивает привязки для свободных переменных в этом коде. Обычно это лексическая среда, но нет технической причины, по которой она не может быть динамичной.
Хитрость заключается в том, чтобы закрыть код над средой, а не с конкретными значениями. Это то, что сделал Lisp 1.5, а также то, что сделал MACLisp для "нисходящих funargs".
Вы можете увидеть, как Lisp 1.5 сделал это, прочитав руководство по Lisp 1.5 на http://www.softwarepreservation.org/projects/LISP/book
Обратите особое внимание в Приложении B на то, как eval обрабатывает FUNCTION и как применять обрабатывает FUNARG.
Вы можете получить базовый вид программирования с использованием динамических замыканий с http://c2.com/cgi/wiki?DynamicClosure
Вы можете получить подробное введение в вопросы реализации с ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-199.pdf
Современные языки с динамической областью действия обычно используют поверхностное связывание, где текущее значение каждой переменной хранится в одном глобальном местоположении, а вызовы функций сохраняют старые значения в стеке. Один из способов реализации динамических замыканий с мелкой привязкой описан по адресу http://www.pipeline.com/~hbaker1/ShallowBinding.html