Les scripteurs sont souvent confus lorsqu'ils tentent d'utiliser une variable comme argument dans une fonction ou un message JSL mais n'obtiennent pas le résultat escompté. Bien qu'il existe de nombreuses circonstances dans JSL où les scripteurs rencontrent cette situation, celle que les utilisateurs rencontrent fréquemment est lorsqu'ils essaient de définir la propriété de colonne Spec Limits. Les valeurs à utiliser comme Spec Limits sont souvent extraites d'une table de recherche dans une étape précédente où elles sont affectées à des variables. Après avoir collecté et affecté toutes les valeurs limites aux variables, l'étape logique suivante consiste à utiliser ces variables pour définir la propriété de colonne dans la table d'analyse. Voici un exemple représentatif de ce qu'un scripteur peut essayer. Vous pouvez copier ce JSL dans une fenêtre de script et l'exécuter pour suivre.
Names Default to Here(1);
// Open a sample data table
dt = Open("$SAMPLE_DATA/Cleansing.jmp");
// Values previously obtained from a lookup table and assigned to variables as:
myLSL = 6;
myUSL = 8;
myTarget = 7;
// Use the variables to set the spec limits column property
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( myLSL ), USL( myUSL ), Target( myTarget ), Show Limits( 1 )}
);
Lorsque ce script est exécuté, l'icône apparaît à côté de la colonne pH indiquant qu'une propriété de colonne est définie, et un clic sur l'icône confirme qu'il s'agit de la propriété Limites de spécification.

Cependant, lorsque vous ouvrez la fenêtre de dialogue Informations sur la colonne pour voir les valeurs des limites de spécification, elles sont manquantes !

Qu'a fait JMP ? Cela semble avoir fonctionné, mais seulement partiellement ! Pourquoi ?!?
Pour enquêter, nous pouvons utiliser JSL pour voir les paramètres de propriété. Peut-être que cela fournira un indice. En évaluant l'expression suivante,
Column(dt, "pH") << Get Property("Spec Limits");
les résultats affichent les informations suivantes écrites dans le journal :
{LSL( myLSL ), USL( myUSL ), Target( myTarget ), Show Limits( 1 )}
Eh bien, voilà, c'est exactement ce que j'ai spécifié, mais pourquoi ne vois-je pas les valeurs qui ont été attribuées aux variables au lieu des variables elles-mêmes ? La réponse à cette question touche au cœur de la confusion : JSL n'évalue pas toujours les arguments suffisamment de fois pour résoudre la valeur attribuée, et le nombre de fois où les arguments sont évalués varie selon les circonstances dans lesquelles les variables sont utilisées. Par exemple, dans le contexte actuel, JMP « analyse » l'argument de liste pour comprendre qu'il existe des éléments pour spécifier différents aspects de la propriété Spec Limits. C'est une évaluation. Dans une autre évaluation, JMP examine les éléments de la liste pour déterminer les limites (LSL, USL, Target, etc.) à définir dans la propriété Spec Limits. JMP n'évalue pas du tout les arguments fournis dans les éléments de la liste (myLSL, myUSL, myTarget). JMP attend des valeurs numériques comme arguments pour LSL, USL et Target. Lorsqu'une variable est fournie, JMP ne la reconnaît pas et ne tente pas de résoudre la variable pour déterminer la valeur associée.
Alors, puis-je savoir combien de fois un argument sera évalué dans une circonstance donnée ? Que puis-je faire si j'ai besoin de plus d'évaluations, comme dans l'exemple ci-dessus ? Comme nous n'avons pas accès au code source de JMP, il est très difficile de savoir combien d'évaluations seront effectuées dans une circonstance donnée. Cependant, cela est moins important que de savoir si c'est suffisant pour l'utilisation actuelle. La première chose que je fais est d'essayer de vérifier !
Sans savoir au préalable comment le message Limites de spécification attend des valeurs, j'écris mon script exactement comme indiqué ci-dessus. Ensuite, je vérifie si la limite de spécification a été définie en la vérifiant dans la boîte de dialogue Informations sur la colonne ou en créant un graphique avec la colonne pour voir si les lignes de référence du graphique apparaissent comme elles le devraient. Si la vérification échoue, comme dans ce cas, je dois modifier mon expression pour supprimer les variables et coder en dur les valeurs numériques à la place.
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
J'exécute ensuite l'expression pour vérifier que le problème vient de mon utilisation de variables et non d'un autre problème de syntaxe. Après avoir confirmé que l'expression fournit le résultat attendu avec les valeurs codées en dur, je sais que j'ai rencontré une situation dans laquelle ma variable n'est pas suffisamment évaluée pour atteindre la valeur attribuée. Par conséquent, je dois demander à JMP de créer l'expression de manière dynamique au moment de l'exécution pour y incorporer les valeurs des variables avant d'évaluer l'expression.
Il existe plusieurs façons de préévaluer une variable, mais ma méthode préférée est d'utiliser la fonction Eval Expr(). D'autres méthodes incluent l'utilisation de la fonction Substitute() ou la création de l'expression JSL en concaténant des chaînes, puis en analysant et en évaluant la chaîne finale. De loin, ma méthode la moins préférée est la création de l'expression sous forme de chaîne. Le code est très difficile à lire car il est monochromatique, je perds donc le formatage sémantique utile fourni par l'éditeur JSL et les guillemets intégrés doivent être échappés. Pire encore, le code est difficile à déboguer et à dépanner car je perds la possibilité d'évaluer des parties sélectionnées du code.
// An example of concatenating strings to dynamically write a JSL expression.
Parse(
"Column( dt, \!"pH\!" ) << Set Property(
\!"Spec Limits\!",
{LSL( " || Char(myLSL) || " ), USL( " || Char(myUSL) || " ), Target( " || Char(myTarget) || " ), Show Limits( 1 )}
)"
)
L'utilisation de la fonction Substitute() est meilleure à cet égard, mais si l'expression est longue, je trouve difficile de lire l'expression tout en regardant les derniers arguments qui spécifient quoi et où les substitutions sont effectuées.
// An example of using Substitute() to dynamically write a JSL expression.
Substitute(
Expr(Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( lll ), USL( uuu ), Target( ttt), Show Limits( 1 )}
))
,
Expr(lll), myLSL,
Expr(uuu), myUSL,
Expr(ttt), myTarget
)
En revanche, la fonction Eval Expr() permet une spécification de substitution en ligne et, puisque l'argument de la fonction est une expression, l'éditeur JSL est capable de l'afficher avec le formatage sémantique.
Comment fonctionne Eval Expr() ? C'est une fonction qui prend une expression comme seul argument et renvoie une expression. Elle recherche le jeton Expr() dans l'expression fournie. JMP évalue ensuite ce qui se trouve à l'intérieur des parenthèses de Expr() et remplace le jeton entier par la valeur de retour. Pour revenir à l'exemple ci-dessus pour définir les limites de spécification, si j'enveloppe mes variables avec Expr() et que je place l'expression entière dans un appel Eval Expr(), JMP remplacera mes variables (et le jeton Expr()) par les valeurs des variables au moment de l'exécution et renverra l'expression modifiée. Donc,
// An example of using Eval Expr() to dynamically write a JSL expression.
Eval Expr(
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( Expr(myLSL) ), USL( Expr(myUSL) ), Target( Expr(myTarget) ), Show Limits( 1 )} );
);
retours:
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
C'est super ! J'ai maintenant une expression pour définir la propriété Spec Limits qui inclut les valeurs codées en dur souhaitées. Je viens d'écrire du code JSL de manière dynamique ! Il ne me reste plus qu'à évaluer cette expression modifiée. Pour cela, la fonction Eval() est utile. Je peux encapsuler l'Eval Expr(), appeler un appel Eval(), et l'expression renvoyée par Eval Expr() sera immédiatement évaluée. Voici un exemple de script complet qui définira correctement la propriété Spec Limits en utilisant des valeurs limites connues uniquement au moment de l'exécution :
Names Default to Here(1);
// Open a sample data table
dt = Open("$SAMPLE_DATA/Cleansing.jmp");
// Values previously obtained from a lookup table and assigned to variables as:
myLSL = 6;
myUSL = 8;
myTarget = 7;
// Use the variables to set the spec limits column property
Eval(Eval Expr(
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( Expr(myLSL) ), USL( Expr(myUSL) ), Target( Expr(myTarget) ), Show Limits( 1 )}
);
));
Maintenant, lorsque je vérifie ce script, je vois des valeurs pour les limites de spécification dans la boîte de dialogue Informations sur la colonne.

De plus, l’évaluation de cette expression
Column(dt, "pH") << Get Property("Spec Limits");
les résultats affichent les informations suivantes écrites dans le journal :
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
Enfin, si je crée un graphique avec la colonne, je vois les lignes de référence Spec Limit aux emplacements attendus.

L'écriture dynamique de code JSL est une compétence utile à développer pour un scripteur. Il existe de nombreuses circonstances dans lesquelles JMP n'évalue pas suffisamment de fois un argument dans une expression pour obtenir la valeur réelle requise. Bien qu'il existe plusieurs techniques pour écrire du code JSL de manière dynamique, ma méthode préférée est ce que j'appelle la méthode Eval(EvalExpr(Expr())). Elle permet la substitution en ligne et le formatage sémantique, ce qui rend la lecture et le débogage du code relativement faciles.