Gli scripter sono spesso confusi quando tentano di usare una variabile come argomento in una funzione o messaggio JSL ma non ottengono il risultato previsto. Sebbene vi siano molte circostanze in JSL in cui gli scripter incontrano questa situazione, quella che gli utenti incontrano più frequentemente è quando provano a impostare la proprietà della colonna Spec Limits. I valori da usare come Spec Limits vengono spesso estratti da una tabella di ricerca in un passaggio precedente in cui vengono assegnati a variabili. Dopo aver raccolto e assegnato tutti i valori limite alle variabili, il passaggio logico successivo è usare queste variabili per impostare la proprietà della colonna nella tabella di analisi. Ecco un esempio rappresentativo di ciò che uno scripter potrebbe provare. Puoi copiare questo JSL in una finestra di scripting ed eseguirlo per seguire.
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 )}
);
Quando questo script viene eseguito, l'icona appare accanto alla colonna pH, a indicare che è impostata una proprietà della colonna; cliccando sull'icona si conferma che si tratta della proprietà Limiti specifiche.

Tuttavia, quando si apre la finestra di dialogo Informazioni colonna per visualizzare i valori per i limiti delle specifiche, questi risultano mancanti!

Cosa ha fatto JMP? Sembrava funzionare, ma solo in parte! Perché?!?
Per indagare, possiamo usare JSL per vedere le impostazioni delle proprietà. Forse fare questo fornirà un indizio. Valutando la seguente espressione,
Column(dt, "pH") << Get Property("Spec Limits");
si traduce nelle seguenti informazioni scritte nel registro:
{LSL( myLSL ), USL( myUSL ), Target( myTarget ), Show Limits( 1 )}
Bene, eccolo, esattamente quello che ho specificato, ma perché non vedo i valori assegnati alle variabili invece delle variabili stesse? La risposta a questa domanda arriva al nocciolo della confusione: JSL non valuta sempre gli argomenti abbastanza volte per risolvere il valore assegnato e il numero di volte in cui gli argomenti vengono valutati varia a seconda delle circostanze in cui vengono utilizzate le variabili. Ad esempio, nel contesto attuale JMP "analizza" l'argomento elenco per comprendere che ci sono elementi per specificare diversi aspetti della proprietà Limiti spec. Questa è una valutazione. In un'altra valutazione, JMP esamina gli elementi dell'elenco per determinare quali limiti (LSL, USL, Target, ecc.) impostare nella proprietà Limiti spec. JMP non valuta affatto gli argomenti forniti all'interno degli elementi dell'elenco (myLSL, myUSL, myTarget). JMP si aspetta valori numerici come argomenti per LSL, USL e Target. Quando viene fornita una variabile, JMP non la riconosce e non tenta di risolvere la variabile per determinare il valore associato.
Quindi, posso sapere quante volte un argomento verrà valutato in una data circostanza? Cosa posso fare se ho bisogno di più valutazioni, come nell'esempio sopra? Dal momento che non abbiamo accesso al codice sorgente di JMP, è molto difficile sapere quante valutazioni verranno eseguite in una data circostanza. Tuttavia, questo è meno importante che sapere se è sufficiente per l'uso attuale. La prima cosa che faccio è provare e verificare!
Senza una conoscenza preliminare di come il messaggio Spec Limits si aspetta i valori, scrivo il mio script esattamente come mostrato inizialmente sopra. Poi, controllo se Spec Limit è stato impostato esaminandolo nella finestra di dialogo Column Info o creando un grafico con la colonna per vedere se le Graph Reference Lines appaiono come dovrebbero. Se la verifica fallisce, come in questo caso, devo modificare la mia espressione per rimuovere le variabili e codificare in modo rigido i valori numerici.
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
Quindi eseguo l'espressione per verificare che il problema riguardi il mio utilizzo delle variabili e non qualche altro problema di sintassi. Dopo aver confermato che l'espressione fornisce il risultato previsto con i valori hard-coded, so di aver riscontrato una circostanza in cui la mia variabile non viene valutata abbastanza per arrivare al valore assegnato. Pertanto, ho bisogno che JMP crei l'espressione dinamicamente in fase di esecuzione per incorporare i valori delle variabili in essa prima di valutare l'espressione.
Ora, ci sono diversi modi per pre-valutare una variabile, ma il mio metodo preferito è usare la funzione Eval Expr(). Altri metodi includono l'uso della funzione Substitute() o la creazione dell'espressione JSL concatenando stringhe, quindi analizzando e valutando la stringa finale. Di gran lunga il mio metodo meno preferito è la creazione dell'espressione come stringa. Il codice è molto difficile da leggere perché è monocromatico, quindi perdo la formattazione semantica utile fornita dall'editor JSL e le virgolette incorporate devono essere sottoposte a escape. Ancora peggio, il codice è difficile da debuggare e risolvere perché perdo la capacità di valutare parti selezionate del codice.
// 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 )}
)"
)
In questo caso, è meglio usare la funzione Substitute(), ma se l'espressione è lunga, trovo difficile leggerla esaminando anche gli argomenti successivi che specificano quali e dove vengono effettuate le sostituzioni.
// 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
)
Al contrario, la funzione Eval Expr() consente la specifica della sostituzione in linea e, poiché l'argomento della funzione è un'espressione, l'editor JSL è in grado di visualizzarlo con la formattazione semantica.
Quindi, come funziona Eval Expr()? È una funzione che accetta un'espressione come unico argomento e restituisce un'espressione. Cerca l'espressione fornita per il token Expr(). JMP valuta quindi ciò che è all'interno delle parentesi di Expr() e sostituisce l'intero token con il valore restituito. Tornando all'esempio precedente per impostare i limiti delle specifiche, se "avvolgo" le mie variabili con Expr() e inserisco l'intera espressione in una chiamata Eval Expr(), JMP sostituirà le mie variabili (e il token Expr()) con i valori delle variabili in fase di esecuzione e restituirà l'espressione modificata. Quindi,
// 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 )} );
);
ritorna:
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
Fantastico! Ora ho un'espressione per impostare la proprietà Spec Limits che include i valori hard-coded desiderati. Ho appena scritto codice JSL dinamicamente! Ora devo solo valutare questa espressione modificata. Per questo, la funzione Eval() è utile. Posso avvolgere Eval Expr(), chiamare in una chiamata Eval() e l'espressione restituita da Eval Expr() verrà immediatamente valutata. Ecco uno script di esempio completo che imposterà correttamente la proprietà Spec Limits utilizzando valori limite noti solo in fase di esecuzione:
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 )}
);
));
Ora, quando verifico questo script, vedo i valori per i limiti delle specifiche nella finestra di dialogo Informazioni sulla colonna.

Inoltre, valutando questa espressione
Column(dt, "pH") << Get Property("Spec Limits");
si traduce nelle seguenti informazioni scritte nel registro:
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
Infine, se creo un grafico con la colonna, vedo le linee di riferimento del limite di specifica nelle posizioni previste.

Scrivere codice JSL in modo dinamico è un'abilità utile da sviluppare per uno scripter. Ci sono molte circostanze in cui JMP non valuta un argomento in un'espressione abbastanza volte per arrivare al valore effettivo necessario. Sebbene esistano diverse tecniche per scrivere codice JSL in modo dinamico, il mio metodo preferito è quello che chiamo metodo Eval(EvalExpr(Expr())). Consente la sostituzione in linea e la formattazione semantica, che rendono la lettura e il debug del codice relativamente semplici.