Подтвердить что ты не робот

Помимо логотипа и Emacs Lisp, что такое другие чистые языки с динамическим охватом?

Каковы некоторые примеры языка с динамическим охватом? И в чем причины выбора этого дизайна? Это потому, что его легко реализовать?

4b9b3361

Ответ 1

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

Динамические переменные могут быть "непредсказуемыми" во время выполнения, потому что нужно знать, в каком порядке фактические стековые кадры должны знать, какая переменная будет использоваться. Эта информация недоступна, просто глядя на статическую структуру кода. Можно было бы легко поймать, если фактический график вызовов программы непросто предсказать во время реализации. Вот почему большинство языков сегодня имеют статическую шкалу (большинство систем исключений, однако, являются динамическими, поскольку это наиболее практично).

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

(let ((*standard-output* *some-other-stream*))
 (stuff))

В этом примере common- lisp (от Seibel) стандартный вывод привязан к другому потоку на протяжении всей формы let (внутри его закрывающих парнеров). Когда исполнение покидает let, оно возвращается к тому, что было заранее. Смотрите http://gigamonkeys.com/book/variables.html Питер Сейбелс свободная и отличная книга "Практический общий Lisp" для хорошего обсуждения. В "Сейблз" собственные слова:

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

Ответ 2

Mathematica - это другой язык, который динамически ограничен, через конструкцию Block. Это действительно полезно при работе с формулами. Это позволяет вам писать такие вещи, как

 In[1]:= expr = a*t^2 + b*t+ c;

 In[2]:= Block[{a = 1, b = -1, c = 2}, Table[expr, {t, 5}]]
 Out[2]= {2, 4, 8, 14, 22}

который не работал бы вообще, если бы такие переменные, как a и t, были лексически охвачены. Он особенно хорошо работает с системой перезаписи правил Mathematica, которая, помимо прочего, оставит переменные неоценимыми (как символические выражения), если у них нет существующего определения для них.

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

Module[{x = 4}, 
  Table[x * t, {t, 5}]]

превратится в нечто вроде этого:

Block[{x$134 = 4},
  Table[x$134 * t, {t, 5}]

Emacs Lisp в одной из своих библиотек имеет конструкцию (на самом деле макрос Lisp), называемый lexical-let, который тянет точно такой же трюк, чтобы подделать лексическое охват.

Существуют преимущества производительности для реального лексического охвата при компиляции вашего языка, который вы не получаете с ложными лексиками ELisp или Mathematica, так как вам нужно некоторое сопоставление между динамической переменной и ее текущим значением, что означает выполнение (через хеш-таблицу или список свойств или что-то еще) и дополнительные слои косвенности.

EDIT. Если у вас есть только лексические переменные, вы можете подделывать динамическое масштабирование, сохраняя исходное значение глобальной лексической переменной при вводе области и гарантируя, что старое значение восстанавливается после выхода из объем. Чтобы обеспечить это, вам понадобится что-то вроде Lisp UNWIND-PROTECT или finally. Я видел это и с использованием деструкторов С++, в основном как упражнение.

Ответ 3

Ну, там куча веб-сайтов, которые обсуждают про и con, поэтому я туда не поеду.

Одним интересным языком, который имеет некоторые функции, которые слабо напоминают динамическую область, является XSLT; хотя XSLT-шаблоны и переменные и т.д. лексически ограничены, XSLT, конечно же, относится к XML, а текущая позиция в дереве xml "динамически ограничена" в том смысле, что контекст node является глобальным и, следовательно, выражения XPath оценивается не в соответствии с лексической областью XSLT, но в соответствии с ней динамическая оценка.

Ответ 4

Динамический охват/проще выполнять с помощью интерпретаторов. Большинство ранних переводчиков Lisp использовали динамический охват. Было установлено, что через несколько лет лексическая область имеет преимущество, но в основном была реализована в компиляторах Lisp. Появилось несколько реализаций, в которых реализована динамическая область в интерпретированном коде и лексической области в скомпилированном коде. Некоторые из них предоставили специальную языковую конструкцию для обеспечения закрытия. Lisp диалекты, такие как Scheme и Common Lisp, необходимы тогда, когда нет никакой разницы между интерпретированным и скомпилированным кодом, и поэтому интерпретированные на основе реализации также должны были реализовать лексическую область.

В ранних реализациях Smalltalk реализована динамическая область. Все виды реализаций диалектов Lisp реализовали динамическую область (Interlisp, UCI Lisp, Lisp Machine Lisp, MacLisp,...).

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

Ответ 5

Все языки оболочки (bash, ksh и т.д.) используют динамическое масштабирование.