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

В чем преимущества динамического обзора?

Я узнал, что статический охват - единственный разумный способ сделать что-то, а динамическое масштабирование является инструментом дьявола, и это результат только из-за плохих реализаций интерпретаторов/компиляторов.

Затем я увидел этот фрагмент из Common Lisp vs. Scheme:

Both Lexically and Dynamically    Lexical scope only, per the standard.
scoped special vars.  Common      Dynamically scoped vars are provided
Lisp just wins on this point.     by some implementations as an extension
                                  but code using them is not portable.

     (I have heard the arguments about whether Dynamic scoping
      is or is not a Bad Idea in the first place.  I don't care. 
      I'm just noting that you can do things with it that you 
      can't easily do without it.)

Почему Common Lisp "просто выиграть в этом пункте"? Что легче делать с динамическим охватом? Я действительно не могу оправдать, когда-либо нуждающийся в этом/видя, что это хорошо.

4b9b3361

Ответ 1

Как и все остальное, Dynamic Scoping - всего лишь инструмент. Используемый хорошо, он может облегчить выполнение определенных задач. Используется плохо, это может привести к ошибкам и головным болям.

Я могу, конечно, увидеть некоторые возможности для этого. Можно избавиться от необходимости передавать переменные некоторым функциям.

Например, я могу настроить отображение в начале программы, и каждая графическая операция просто предполагает этот дисплей.

Если я хочу настроить окно внутри этого экрана, тогда я могу "добавить" это окно в стек переменных, который иначе определяет отображение, и любые графические операции, выполняемые в этом состоянии, будут идти в окно, а не в отображение в целом.

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

-Adam

Ответ 2

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

Динамическая область действия, насколько это полезно, полезно для поведения, которое должно быть чувствительным к стеку времени выполнения. Например (и, вообще говоря, не относится к Lisp или вариантам):

  • обработка исключений - самый верхний блок catch - это тот, который является "в области видимости", когда возникает исключение.
  • безопасность. Безопасность на основе кода .NET принимает решения о доступности определенных привилегированных API-интерфейсов на основе того, какой код он назвал.

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

Ответ 3

Динамическое масштабирование полезно на некоторых языках, относящихся к конкретным доменам. В частности, он может быть ручным в языках стилей. Мой опыт связан с языком стилей GNU TeXmacs.

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

Динамическое масштабирование в TeXmacs также используется, среди прочего, для обозначения перекрестных ссылок. Якоря, используемые для перекрестных ссылок, получают свою метку из своей среды. Например, якорь, включенный в блок формулы, будет использовать номер формулы в качестве метки вместо номера раздела для якоря, расположенного после формулы.

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

Как отметил Барри Келли , динамическое определение области охвата также может быть полезно для реализации языковых функций, которые заботятся о сфере вызовов, таких как обработка исключений или зависящая от контекста обработка разрешений, При наличии продолжений области можно вводить и выходить без прохождения через стек вызовов.

Ответ 4

Динамическая область позволяет определять контекстные функции. В этом смысле он очень похож на инъекцию зависимостей в современных рамках. (Например, рассмотрите, когда вы аннотируете класс Java с определениями вложений зависимостей, чтобы разрешить прозрачную инициализацию различных ссылок. (Cf spring или JPA и т.д.))

Очевидно, что динамическое масштабирование делает определенные предположения относительно характеристик времени выполнения сайта вызова для данной функции, которые не могут быть гарантированы при компиляции (или в дизайне) времени. Опять же, следуя примеру современного компонента (Java) framework, если вы создаете экземпляр такого класса вне контролируемой среды (среды выполнения) контейнера, легко можно, что класс не сможет функционировать, учитывая, что его требуемые зависимости не будут инициализированы (они также введены).

Но одинаково очевидно, что системы компонентов (как только один пример) явно выигрывают от динамических механизмов привязки. Инъекционная инъекция - это средство, обеспечивающее его уровень. Динамическое масштабирование - это уровень языкового уровня.

Ответ 5

Также обратите внимание, что объединение

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

может оказаться сложным делом, как с точки зрения языковой реализации, так и с точки зрения программиста. Для этой сложной вещи есть даже специальное название: закрытие.

Как Википедия пишет:

Правильная реализация статической области на языках с первоклассным вложенным функции не тривиальны, так как это требует, чтобы каждое значение функции переносилось с ним запись значений переменные, от которых оно зависит (пара функции и этой среды называется замыканием).

Это не просто нетривиально для реализации в langauge с глобальными и/или изменяемыми переменными (например, C или Java, подумайте об обеспечении правильного доступа на момент оценки закрытия в изменяемое состояние, которое было в области на месте определения вложенной функции! Только одно: используемые объекты не должны были быть разрушены и собраны с помощью мусора, когда вы оцениваете закрытие в будущем), но также это не тривиально концептуально для программист, чтобы подумать о том, как закрытие будет работать в сложной ситуации и какие (побочные) эффекты будут точно иметь (по той же причине: вам нужно подумать о взаимодействии замыкания со всем изменчивым состоянием, был в том объеме, когда вы определили замыкание, например: Когда вы ссылаетесь на определение закрытия на внешнюю изменяемую переменную, которая находится в области видимости, , вы действительно хотите получить доступ к значению, которое имела переменная во время определения закрытие, т.е. вы хотите иметь копию только для чтения переменной или вам нужен полный доступ к изменяемому состоянию переменной в будущем во время оценки закрытия?).

В чистых функциональных языках гораздо проще думать о вложенных определениях функций и их использовании, и поэтому наличие только лексической области не является проблемой для них вообще. Но если ваш язык не работает, это не так тривиально. (Я считаю, что это одна из причин того, что долгое время обсуждалось, как добавить закрытие Java: они, похоже, не были достаточно тривиальными, чтобы понять программиста, хотя они просто основываются на хорошей концепции лексического охвата.)

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

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

Примечания

Относительно долгой истории (нет) замыканий в Java (и что программистам не понравилось понятие) - http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg04030.html

Дата: Чт, 14 авг 2003 08:05:44 -0700

От: Майкл Ванье

Тема: Re: привязки и назначения (было: Re: continue)

Дата: Чт, 14 авг 2003 10:45:34 -0400

     

От: "Дэвид Б. Такер"

     
  

Я полагаю, хотя у меня нет статистических данных, что     требование объявить локальные переменные окончательными, чтобы     ссылаться на них внутри анонимных внутренних классов (закрытий) почти     полностью неизвестным и неиспользуемым на практике.

  
  

Из любопытства кто-нибудь знает, почему Java допускает окончательное   переменные   для ссылки на анонимные классы?

     

Dave

   <cynic>Otherwise you'd have the equivalent of true closures,
and if you had that    java would be a
*really* powerful and useful language, so they obviously    couldn't do that.
</cynic>

Собственно, реализация прототипа позволяли ссылаться на не конечные переменные из внутренних классов. Был протест от пользователей, жалуясь, что они не хотят это! Причина была интересной: в для поддержки таких переменных, это было необходимо, чтобы кучи-выделить их, и (в то время, по крайней мере) средний программист Java по-прежнему довольно пугливый о распределении кучи и сбор мусора и все такое. Они не одобряли язык выполнение распределения кучи "в соответствии с таблицы", когда не было "новое" ключевое слово в поле зрения.

Итак, в первые дни - по-видимому - "третий" подход (в отличие от двух, упомянутых выше в моем тексте выше) должен был быть взят на Java: ни "копии только для чтения", ни реальные доступ во время оценки к охватывающему (во время определения закрытия) изменяемому состоянию, а скорее изменяемым копиям государства (по крайней мере, я понимаю цитируемый проход таким образом, или нет, он говорит о heap-allocating только ссылки?.. Тогда это второй вариант. Хорошо. Третий вариант действительно выглядит неразумно для меня.). Не уверен, как они реализуют закрытие в настоящее время в Java, я не слежу за новыми последними материалами о Java.

Ответ 6

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

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

Или подумайте об исключениях: они динамически охвачены большинством языков. Если вам нужно было создать систему исключений с нуля, вы можете легко сделать это с помощью динамически измененных переменных.

Ответ 7

В этой классической статье Ричарда Столлмана (GNU/Linux, Emacs, FSF) объясняется, почему динамическое масштабирование важно для редактора Emacs и языка Emacs Lisp. В целом, это полезно для настройки.

http://www.gnu.org/software/emacs/emacs-paper.html#SEC17

См. также эту страницу в вики Emacs для получения дополнительной информации об использовании динамического охвата в Emacs Lisp:

Ответ 8

Я думаю, что динамическая область в Common LISP является аналогией глобальной переменной в C. Использование их в функциональных функциях проблематично.

Ответ 9

Динамическое масштабирование Референциальная прозрачность, что означает, что вы больше не можете рассуждать о программе. DS - это в основном глобальные переменные на стероидах.

Ответ 10

Пример, удобный для меня в способе привязки Emacs - не уверен, что лексический или динамический - это правильный термин BTW.

Переменная, связанная внутри let, рассматривается вниз, без явной передачи в качестве аргумента, которая экономит много нажатий клавиш.

(defun foo1 ()
  (message "%s" a))

(defun foo2 ()
  (let ((a 2))
  (message "%s" a)))

(defun foo3 ()
  (let ((a 1))
    (foo1)
    (foo2)))

==>
1
2

Взаимосвязь внутри foo2 представляет интерес, так как здесь могут быть установлены значения по умолчанию.

(пусть ((a (если (eq что-то a) назначить иначе...