Portée JMP - Portée dynamique vs. portée lexicale et confusion générale apprentissage JSLSi je me trompe, corrigez-moi, mais il semblerait que JMP ait une portée dynamique sans persistance de portée (à l'exception des pseudo-espaces de noms Ici , Fenêtre , Boîte ).Cela contraste avec de nombreux langages de programmation populaires qui ont une portée lexicale avec une persistance complète à l'aide de compteurs de références.
Cela m'a causé beaucoup de casse-tête jusqu'à ce que j'acquière l'intuition nécessaire pour travailler avec le système de portée étrange de JMP, et je pense que c'est un grand point de confusion pour beaucoup de gens.Peu de langages de programmation utilisent la portée dynamique (LISP étant une exception importante, et JSL présente certaines similitudes avec LISP).
J'encourage l'équipe de documentation JSL à souligner cette distinction et à fournir des ressources/liens sur la façon de mieux comprendre la portée dynamique car ce n'est certainement pas la manière standard de faire la résolution de noms.
Voici un exemple : la portée locale de la fonction externe est effacée immédiatement après l'instruction de retour, et la résolution de nom des fonctions internes est dynamique (basée sur la pile d'appels actuelle) :
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 vous faites quelque chose d'équivalent sur le plan fonctionnel dans un langage à portée lexicale avec persistance de portée (comme Python), alors la portée englobante de la fonction interne est persistante (c'est la portée locale pour la fonction externe), et la résolution de nom pour la fonction interne la variable x de la fonction est la valeur 4 issue de la lecture lexicale du système.Étant donné que JMP n'utilise pas la portée lexicale, mais utilise la portée dynamique, alors lorsque la fonction interne est finalement exécutée à la fin du script, elle utilise la résolution de nom dynamique de Local -> Ici -> Global (et éventuellement la colonne- noms pour la table courante) et trouve la valeur 7.
Comprendre ce type de comportement est essentiel pour créer des programmes robustes en JSL, et je veux juste le signaler à tous ceux qui apprennent / luttent avec JSL.
Faites-moi savoir si vous avez des idées / des exemples non intuitifs !
Automatisation et scriptAccès aux donnéesRe: Portée JMP - Portée dynamique vs. portée lexicale et confusion générale apprentissage JSLC'est vrai, et cela m'a définitivement jeté dans une boucle lors de l'apprentissage de la langue.L'autre problème est que JSL est un Langage de réécriture de termes grâce à ses objets d'expression, ce qui signifie que tout en étant LISP-ish en ce qui concerne la portée, n'est pas LISP-ish en ce qui concerne la façon dont il gère les macros.
Le seul autre langage de réécriture de termes que je connaisse et qui est couramment utilisé est Wolfram Language.Je ne connais pas assez bien CS pour en être sûr, mais j'ai entendu certaines personnes prétendre que le paradigme de réécriture de termes est strictement plus puissant que les macros de Lisp.D'un autre côté, j'ai entendu certains prétendre que Wolfram Language est simplement une implémentation d'expressions m, où Lisp a décidé que les expressions s étaient assez bonnes.
Quoi qu'il en soit, le système d'expression de JSL sera étranger à presque tout le monde, et l'ergonomie de leurs fonctions pour travailler avec des expressions ne leur rend pas service.Il y a une raison pour laquelle vous pouvez trouver autant d'exemples dans ce forum de personnes utilisant la manipulation de chaînes et Parse() au lieu des fonctionnalités de réécriture de termes.
Re: Portée JMP - Portée dynamique vs. portée lexicale et confusion générale apprentissage JSLJe ne suis pas un CS moi-même, mais ce truc sur la réécriture de termes est assez intéressant !Merci pour la référence, je serai debout toute la nuit sur ce trou de lapin maintenant...
Re : Portée JMP – Portée dynamique vs. lexicale et confusion générale lors de l’apprentissage du JSLLe
func = outer function;
func();
Cela m'a intrigué.
Après exécution
func = outer function();
La définition de la fonction interne est stockée dans la variable func.
C'est pourquoi Afficher(fonction) renvoie
func = Function({},Print(x));
À ce stade, toutes les informations concernant la fonction externe et la fonction interne ont disparu.
Donc fonction() exécutera Print(x) et ... affichera 7 .
modifier:
En fait, il n'y a rien de nouveau par rapport à ce qui a été écrit dans le message principal.
Simplement la « vue 2D » d'un programmeur JSL.
Re : Portée JMP – Portée dynamique vs. lexicale et confusion générale lors de l’apprentissage du JSLJMP conserve les variables telles quelles dans la définition de la fonction ; il ne les remplace pas automatiquement par leur valeur actuelle.
Donc, après
x = 4;
inner function = Function( {}, Print( x ));
inner function is defined as
Function( {}, Print( x ));
Pour que la fonction interne remplace son x par le x de la fonction externe , une pré-évaluation est nécessaire, comme par exemple :
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
Édit : même vue 2D avec d'autres mots.
Re : Portée JMP – Portée dynamique vs. lexicale et confusion générale lors de l’apprentissage du JSLJ'ai jeté un coup d'œil rapide par-dessus la clôture :
def outer():
y=4
def inner():
print(y)
return inner
f = outer()
y = 7
f() # -> 4
Python renvoie donc 3. Car c'est ainsi que y est défini dans le contexte lexical lorsque inner est défini.
« Défini » ou « retourné » ?
Regardons de plus près :
def outer():
y=4
def inner():
print(y)
y=-100
return inner
f = outer()
y = 7
f()
-> -100