Ámbito JMP -- Ámbito dinámico vs. léxico y confusión general aprendiendo JSLSi me equivoco, corríjame, pero parece que JMP tiene un alcance dinámico sin persistencia de alcance (excepto los pseudo-espacios de nombres Aquí , Ventana , Caja ).Esto contrasta con muchos lenguajes de programación populares que tienen alcance léxico con persistencia de alcance completo utilizando contadores de referencia.
Esto me causó muchos problemas hasta que obtuve la intuición necesaria para trabajar con el extraño sistema de alcance que tiene JMP, y creo que es un gran punto de confusión para muchas personas.No muchos lenguajes de programación usan el alcance dinámico (LISP es una excepción importante, y JSL tiene algunas similitudes con LISP).
Animo al equipo de documentación de JSL a señalar esta distinción y proporcionar algunos recursos/enlaces sobre cómo comprender mejor el alcance dinámico, ya que ciertamente no es la forma estándar de hacer la resolución de nombres.
Aquí hay un ejemplo: el alcance local de la función externa se borra inmediatamente después de la declaración de devolución, y la resolución de nombres de las funciones internas es dinámica (basada en la pila de llamadas actual):
Names Default to Here( 1 );
x = 7;
outer function = Function( {},
{x},
x = 4;
inner function = Function( {},
Print( x )
);
Return( Name Expr( inner function ) );
);
func = outer function;
func()
/*** OUTPUT ***
7Si hace algo funcionalmente equivalente en un lenguaje de alcance léxico con persistencia de alcance (como Python), entonces el alcance de cierre de la función interna es persistente (es el alcance local para la función externa) y la resolución de nombre para el interno La variable x de la función es el valor 4 de la lectura léxica del sistema.Dado que JMP no usa el alcance léxico, pero usa el alcance dinámico, cuando la función interna finalmente se ejecuta al final del script, usa la resolución dinámica de nombres de Local -> Aquí -> Global (y posible columna- nombres para la tabla actual) y encuentra el valor 7.
Comprender este tipo de comportamiento es fundamental para crear programas sólidos en JSL, y solo quiero señalarlo a cualquiera que esté aprendiendo/luchando con JSL.
¡Avíseme si tiene alguna idea o ejemplo poco intuitivo!
Automatización y secuencias de comandosAcceso a los datosRe: Ámbito JMP -- Ámbito dinámico vs. léxico y confusión general aprendiendo JSLEsto es cierto, y definitivamente me desconcertó al aprender el idioma.La otra arruga es que JSL es un Lenguaje de reescritura de términos gracias a sus objetos de expresión, lo que significa que si bien es LISP-ish con respecto al alcance, no es LISP-ish con respecto a cómo maneja las macros.
El único otro lenguaje de reescritura de términos que conozco en uso popular es Wolfram Language.No estoy lo suficientemente versado en CS para decirlo con certeza, pero he escuchado a algunas personas alegar que el paradigma de reescritura de términos es estrictamente más poderoso que las macros de Lisp.Por otro lado, he escuchado algunas afirmaciones de que Wolfram Language es simplemente una implementación de expresiones m, donde Lisp decidió que las expresiones s eran lo suficientemente buenas.
De todos modos, el sistema de expresión de JSL será extraño para casi todos, y la ergonomía de sus funciones para trabajar con expresiones no les hace ningún favor.Hay una razón por la que puede encontrar tantos ejemplos en este foro de personas que utilizan la manipulación de cadenas y Parse() en lugar de las funciones de reescritura de términos.
Re: Ámbito JMP -- Ámbito dinámico vs. léxico y confusión general aprendiendo JSLYo no soy una persona de CS, ¡pero esto de la reescritura de términos es bastante interesante!Gracias por la referencia, estaré despierto toda la noche en este agujero de conejo ahora...
Re: Ámbito JMP: Ámbito dinámico vs. léxico y confusión general al aprender JSLEl
func = outer function;
func();
Me desconcertó.
Después de ejecutar
func = outer function();
La definición de la función interna se almacena en la variable func.
Es por esto que Mostrar(func) retorna
func = Function({},Print(x));
En este punto, toda la información sobre la función externa y la función interna desaparece.
Entonces función() ejecutará Print(x) y... imprimirá 7 .
editar:
En realidad no hay nada nuevo en comparación con lo escrito en el post principal.
Sólo la "vista 2D" de un programador JSL.
Re: Ámbito JMP: Ámbito dinámico vs. léxico y confusión general al aprender JSLJMP mantiene las variables en la definición de función tal como están: no las reemplaza automáticamente con el valor actual.
Entonces, después
x = 4;
inner function = Function( {}, Print( x ));
inner function is defined as
Function( {}, Print( x ));
Para hacer que la función interna reemplace su x con la x de la función externa , se necesita una evaluación previa como
Names Default to Here( 1 );
x = 7;
outer function = Function( {},
{x},
x = 4;
Eval(Eval Expr( inner function = Function( {},
x= Expr(x);
Print( x )
)));
Return( Name Expr(inner function));
);
func = outer function;
func() // prints 4
editar: misma vista 2D con otras palabras.
Re: Ámbito JMP: Ámbito dinámico vs. léxico y confusión general al aprender JSLEché un vistazo rápido por encima de la valla:
def outer():
y=4
def inner():
print(y)
return inner
f = outer()
y = 7
f() # -> 4
Entonces, Python devuelve 3. Porque así es como se define y en el contexto léxico cuando se define inner.
¿"Definido" o "devuelto"?
Echemos otro vistazo:
def outer():
y=4
def inner():
print(y)
y=-100
return inner
f = outer()
y = 7
f()
-> -100