Re : Besoin d'aide pour comprendre comment les variables sont définies dans les expressionsLa portée se déroule comme ceci – recherche dans Local() espace de noms s'il existe, sinon recherche dans Ici() espace de noms s'il existe, sinon recherche dans Mondial() espace de noms.(En outre, il vérifiera parfois également les noms de colonne de la table de données actuelle).
Ce que vous faites dans votre premier script est de mettre le nom "x"n dans le Ici() espace de noms avec valeur "Variable" , puis mettez le nom "exprA"n dans le Ici() espace de noms avec valeur Write( "Voici la variable : " || x ) , puis mettez le nom "exprB"n dans le Ici() espace de noms avec valeur Colle( dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" ), dt1 << On Close( exprA ) ) .
Enfin tu évalues "exprB"n -- JMP essaie alors de résoudre ce nom en vérifiant d'abord le Local() namespace (il n'existe pas), alors le Ici() namespace et il le trouve - il exécute donc l'expression stockée dans As Scoped( "ici", "exprB" ) .
Cela charge ensuite la table et met exprA comme script de fermeture de la fenêtre.
Puisque c'est la fin du script alors le Ici() l'espace de noms créé pour le script est supprimé et la mémoire est effacée.
Lorsque vous fermez la table, elle trouve le littéral exprA comme script de fermeture, puis il essaie de définir la portée du nom comme ci-dessus (dans Local() , Ici() , Mondial() ), sauf que cette fois il n'y a pas Ici() namespace et il ne peut trouver le nom dans aucun des trois espaces de noms, ce qui génère une erreur.
En général, lorsque vous souhaitez ajouter une variable en tant que valeur statique à une expression qui s'exécutera dans une portée différente, utilisez soit Eval( Eval Expr( ...; Expr( Nom Expr( val ) ); ... ) ) ou un autre équivalent.
Dans mon expérience personnelle, je crée des espaces de noms explicites pour chaque script (anonyme), puis étend manuellement toutes les variables à l'espace de noms respectif.Je peux ensuite passer cet espace de noms selon les besoins (et bien sûr, j'efface et ferme l'espace de noms lorsque le script est terminé / la fenêtre est fermée).
Voici quelques exemples de la manière dont votre script pourrait fonctionner :
Names Default To Here( 1 );
x = "Variable";
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose( Write( "\!NHere is variable: " || Expr( x ) ) );
) );
ou
Names Default To Here( 1 );
x = "Variable";
exprA = Expr(
Write( "\!NHere is variable: " || x )
);
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose( x = "rather"; Expr( Name Expr( exprA ) ) );
) );
ou
Names Default To Here( 1 );
self = New Namespace();
self:x = "Variable";
self:exprA = Expr(
Write( "\!NHere is variable: " || self:x )
);
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose(
Local( {self = Namespace( Expr( self << Get Name ) )},
self:exprA;
Delete Namespaces( Force( 1 ), self )
)
);
) );Notez que bien que de nombreux langages de programmation créent des espaces de noms locaux et les conservent en utilisant des compteurs de références jusqu'à ce qu'ils ne soient plus nécessaires (comme Python avec des fonctions et autres), JSL ne le fait pas vraiment et c'est au codeur de maintenir tout persistance et portée nécessaires. Le code à l'intérieur du <<À la fermeture( ... ) Le message est évalué dans un contexte complètement distinct du script qui l'a créé sans gestion des noms ou des portées.
J'espère que cela vous aidera, cela peut être un peu déroutant !!
Re : Besoin d'aide pour comprendre comment les variables sont définies dans les expressionsJordan, merci beaucoup, ça explique le comportement. J'aime votre méthode proposée avec les espaces de noms, car le vrai script a de nombreuses tables qui partageraient des variables dans leurs instructions OnClose.
Pouvez-vous m'aider à comprendre le bout de code suivant :
Local( {self = Namespace( Expr( self << Get Name ) )},
self:exprA;
Delete Namespaces( Force( 1 ), self )
)Local résout les noms en variables locales, qu'est-ce que cela signifie ? Pourquoi avez-vous besoin de définir certaines variables entre accolades, à quoi cela sert-il ? (l'index de script et la documentation n'en disent pas grand-chose).
Re : Besoin d'aide pour comprendre comment les variables sont définies dans les expressionsRéponse courte - cela empêche les noms d'écraser quoi que ce soit en dehors du Local() bloc.
Longue réponse:
Pour mes fonctions, je les écris comme ceci:
some function = Function( {arg1, arg2, etc},
{Default Local},
self:arg1 = arg1;
self:arg2 = arg2;
//do something amazing!
//call a method:
self:call method
);
call method = Function( {},
//do something else amazing!
1
)
J'utilise ensuite la méta-programmation pour définir soi et injecter une référence dans chaque fonction, qui la transforme en quelque chose comme :
self:some function = Function( {arg1, arg2, etc},
{Default Local},
self = Namespace( "#48" );
self:arg1 = arg1;
self:arg2 = arg2;
//do something amazing!
//call a method:
self:call method
);
self:call method = Function( {},
{self},
self = Namespace( "#48" );
//do something else amazing!
1
)Cela crée quelque chose qui est très similaire aux classes Python (mon code est très différent des déclarations ci-dessus, mais conceptuellement similaire).La chose que je veux qu'il n'arrive jamais, c'est d'avoir la référence soi être écrasé par toute autre valeur.
Imaginez que dans une fonction j'ai un Attendez( 1 ) fonction pour une raison quelconque, et pendant cette phase d'attente quelqu'un ferme une table qui a un script attaché qui redéfinit soi -- lorsque l'instruction d'attente est terminée, alors soi se réfère maintenant à une variable différente et le chaos s'ensuit.
Le Local() La fonction crée un bloc local et toutes les variables définies dans le premier argument (la liste) sont locales à ce bloc, telles que
Names Default to Here( 1 );
a = 1;
b = 4;
Print( "Before Local Block:" );
Show( a, b );
Local(
{local_var1, local_var2, b},
local_var1 = 4;
local_var2 = 2;
b = 9;
Print( "Inside Local Block:" );
Show( local_var1, local_var2, a, b );
a = 5;
);
Print( "After Local Block:" );
Show( Try( local_var1, Empty() ), Try( local_var2, Empty() ), a, b )
/*:
"Before Local Block:"
a = 1;
b = 4;
"Inside Local Block:"
local_var1 = 4;
local_var2 = 2;
a = 1;
b = 9;
"After Local Block:"
Try(local_var1, Empty()) = Empty();
Try(local_var2, Empty()) = Empty();
a = 5;
b = 4;Ici je redéfinis les deux un et b à l'intérieur du bloc local, mais b en dehors du bloc local n'est pas affecté tandis que un est.En mettant soi comme variable locale est l'approche la plus sûre.
Besoin d'aide pour comprendre comment les variables sont portées dans les expressionsBonjour à tous,
J'ai un exemple de script simple. Quelqu'un peut-il m'expliquer quelles sont les portées des variables ici et pourquoi cela fonctionne d'une manière et pas d'une autre?
Voici le script initial :
Names default to here(1);
Clear Globals();
x="Variable";
exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;L'idée est que j'ouvre la table et lui donne une expression dont elle a besoin pour s'exécuter lorsqu'elle est fermée. Expression évalue et modifie (pas dans cet exemple) certaines variables du script.
La façon dont il est écrit ne fonctionne pas - rien ne se passe, mais dans mon vrai script, il est simplement indiqué qu'il ne peut pas trouver de référence.
Bon, essayons de rendre ExprA global :
Names default to here(1);
Clear Globals();
x="Variable";
::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;Maintenant, il voit l'expression, mais cela ne fonctionne toujours pas, car il ne voit plus la variable x.
Ok, rendons x global aussi :
Names default to here(1);
Clear Globals();
::x="Variable";
::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;Maintenant ça marche:
Scriptable[]Here is variable: Variable
// Close Data Table: Big Class
Close( "Big Class" );
La question : pourquoi cela fonctionne-t-il de cette façon et ne fonctionne-t-il pas de la manière initiale ? J'ai regardé moi ça aurait dû marcher.
Je n'aime pas utiliser des variables globales dans ce script - une autre façon de le faire fonctionner ?
Modélisation statistique avancéeAutomatisation et scriptÉtudes de consommation et de marchéAccès aux donnéesFusion et nettoyage des donnéesConception d'expériencesPersonnalisation de masseIngénierie de la qualité et des procédés