Respuesta

3

Bueno, hay un montón de sitios web que hablan sobre los pro y los contras, así que no iré allí.

Un lenguaje interesante que tiene algunas características que se asemejan ligeramente al alcance dinámico es XSLT; aunque las plantillas y variables de XSLT y similares tienen un alcance léxico, XSLT es, por supuesto, todo sobre XML, y la posición actual en el árbol xml tiene "alcance dinámico" en el sentido de que el nodo de contexto es global y por lo tanto las expresiones XPath no se evalúan de acuerdo con el alcance léxico de XSLT, pero de acuerdo con su evaluación dinámica.

7

Mathematica es otro lenguaje que tiene un alcance dinámico, a través del constructo Block. Esto es realmente bastante útil cuando se trabaja con fórmulas. Se le permite escribir cosas como

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} 

que no funcionaría en absoluto si variables como a y t se scoped léxico. Funciona particularmente bien con el sistema de reescritura de reglas de Mathematica, que, entre otras cosas, dejará las variables sin evaluar (como expresiones simbólicas) si no tiene una definición existente para ellas.

Mathematica puede simular el alcance léxico con el constructo Module, pero lo que realmente hace es reescribir la expresión en términos de nuevo símbolo supuestamente único (puede causar enfrentamientos si predice cuál será el próximo símbolo único, lo cual es fácil en la mayoría de los casos). Esto significa

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

se convirtió en algo como esto:

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

Emacs Lisp, en una de sus bibliotecas, tiene una construcción (en realidad una macro Lisp) llamada lexical-let que tira exactamente el mismo truco fingir alcance léxico

Existen ventajas de rendimiento en el alcance léxico real cuando compila el idioma que no obtiene con los léxicos falsos de ELisp o Mathematica, ya que necesita un mapeo entre la variable dinámica y su valor actual, lo que significa haciendo búsquedas (a través de una tabla hash o lista de propiedades o algo así) y capas adicionales de direccionamiento indirecto.

EDITAR: Si tiene sólo las variables léxicas, que pueda ámbito dinámico falsa almacenando el valor original de una variable global, léxica integrarse en el ámbito y garantizar que el valor anterior se restaura al salir del ámbito de aplicación. Para garantizar eso, necesitará algo como el bloque UNWIND-PROTECT de Lisp o un bloque finally. He visto esto hecho usando destructores C++ también, principalmente como un ejercicio.

9

Los idiomas de ámbito dinámico son mucho más fáciles de implementar. Para acceder a las variables que no están en el marco actual de grabación/pila de activación, uno simplemente sigue los enlaces de control. Los enlaces de acceso estático/léxico no son necesarios, lo que hace que los marcos de pila sean más pequeños.

Las variables dinámicas pueden ser "impredecibles" en el tiempo de ejecución, porque es necesario saber en qué orden las estructuras de pila reales sabrán qué variable se utilizará. Esta información no está disponible con solo mirar la estructura estática del código. Uno podría quedar atrapado fácilmente si el gráfico de llamadas real del programa no es fácil de predecir en el momento de la implementación.Es por eso que la mayoría de los idiomas actuales tienen un alcance estático (la mayoría de los sistemas de excepción, sin embargo, son dinámicos ya que es el más práctico).

Sin embargo, en algunos casos, las variables de ámbito dinámico son muy útiles. Por ejemplo, al redirigir la salida, podría usar variables dinámicas para establecer el resultado estándar para el código local y todo el código llamado a partir de allí.

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

En este ejemplo común-lisp (de Seibel), la salida estándar está obligado a otro flujo para la duración de la forma let, (dentro de sus parens de cerramiento). Cuando la ejecución abandona el let, vuelve a ser lo que fue de antemano. Ver http://gigamonkeys.com/book/variables.html Peter Seibels libre y excelente libro, Practical Common Lisp, para una buena discusión. En palabras propias de Seibel:

Los enlaces dinámicos hacen que las variables globales sean mucho más manejables, pero es importante notar que todavía permiten la acción a distancia. La vinculación de una variable global tiene dos efectos de distancia: puede cambiar el comportamiento del código descendente y también abre la posibilidad de que el código descendente asigne un nuevo valor a un enlace establecido más arriba en la pila. Debe usar variables dinámicas solo cuando necesite aprovechar una o ambas de estas características.

3

El alcance dinámico es/fue más fácil de implementar con intérpretes. La mayoría de los primeros intérpretes de Lisp usaban el alcance dinámico. Después de varios años, se descubrió que el alcance léxico tenía una ventaja, pero primero se implementó principalmente en los compiladores Lisp. Aparecieron varias implementaciones que implementaron el alcance dinámico en el código interpretado y el alcance léxico en el código compilado. Algunos proporcionaron una construcción de lenguaje especial para proporcionar cierres. Los dialectos de Lisp como Scheme y Common Lisp requerían entonces que no existiera diferencia entre el código interpretado y el compilado y, por lo tanto, las implementaciones basadas en interpretación tenían que implementar el alcance léxico.

Implementaciones Early Smalltal implementadas en el alcance dinámico. Todos los tipos de implementaciones de dialectos Lisp implementaron alcance dinámico (Interlisp, UCI Lisp, Lisp Machine Lisp, MacLisp, ...).

Casi todos los nuevos dialectos Lisp de los últimos 20 años usan el alcance léxico por defecto o incluso exclusivamente. Varias publicaciones han descrito en detalle cómo implementar Lisp con alcance léxico, por lo que no hay excusa para no usar el ámbito léxico.

2

Todos los lenguajes de shell (bash, ksh, etc.) utilizan el alcance dinámico.

Cuestiones relacionadas