UN question de aandw à propos des formules de colonne a commencé ce post. Si vous utilisez uniquement l'éditeur de formules pour créer des formules de colonne, vous pouvez ignorer presque tout cela. Cet article concerne l'utilisation de JSL pour créer une formule de colonne.
Tout d'abord, un peu sur la commande Formule. En voici une très simple :
The formula for column C adds columns A and BThe formula for column C adds columns A and BThe formula for column C adds columns A and BThe formula for column C adds columns A and BLa formule de la colonne C additionne les colonnes A et B
Le script de table (triangle en haut à gauche->copier le script de table, coller dans un éditeur) ressemble à ceci :
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( :a + :p</img> )
)
)
La ligne 5 définit la formule ; la formule est une expression qui additionne les colonnes a et b. L'expression ne s'exécute que bien plus tard. L'expression est enregistrée, en tant qu'expression, dans le cadre de la colonne. Si une autre ligne est ajoutée au tableau ou si les valeurs des colonnes a ou b sont modifiées, l'expression peut être évaluée à nouveau pour obtenir une valeur pour la colonne c.
C'est un comportement à la fois amical et inhabituel. Inhabituel car la plupart des fonctions évaluent leurs arguments : sqrt( 4 + 5 ) renvoie 3. Convivial, car vous ne voudriez presque jamais que JMP évalue la formule d'une colonne avant qu'elle ne soit affectée à la colonne.
Parfois, une expression de formule peut être vraiment compliquée. Tellement compliqué qu'il serait plus facile d'écrire un programme pour écrire l'expression. Pour ce faire dans la commande de formule, vous auriez besoin d'un moyen de dire à la commande de formule de pré-évaluer l'argument et d'utiliser l'expression résultante comme formule. Pour ce faire, ajoutez un wrapper eval() autour du code à pré-évaluer. Lorsque la commande de formule voit "eval" enveloppé autour de l'expression, elle exécute le code et utilise le résultat.
lookup = function({t,u}, expr(a+b) );
New Table( "abc",
Add Rows( 2 ),
New Column( "a",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( eval( lookup(1,2) ) )
)
)
La fonction "lookup" définie par l'utilisateur (ligne 1) n'est pas très brillante, mais elle doit être exécutée pour récupérer expr(a+b) comme valeur renvoyée. À la ligne 7, le wrapper eval() signifie que la formule de la colonne ne sera pas définie sur "lookup(1,2)", mais à la place sur l'expression renvoyée par lookup(1,2).Même tableau que précédemment, avec la même formule de colonne.
Et si vous vouliez que la formule de la colonne soit définie sur une expression qui commence par eval() ?Comment la commande de formule pourrait-elle faire cela, puisque commencer par eval( ) signifie évaluer l'argument et utiliser le résultat ? (J'aurais eu du mal à trouver un exemple intéressant, mais MME en a un dans la réponse à la question.) La réponse est Nom Expr( ). Name Expr est une fonction JSL normalement utilisée pour extraire une expression d'une variable JSL sans l'évaluer. En tant que wrapper le plus externe dans une commande de formule, il renvoie simplement l'argument sans l'évaluer. Le premier exemple pourrait l'utiliser, sans raison valable si ce n'est cette explication, comme celle-ci, pour retourner exactement la même table :
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( Name Expr( :a + :p</img> ) )
)
)
Mais pour MME Par exemple, il est nécessaire en raison de l'utilisation intelligente de eval (qui souhaite probablement qu'un autre article de blog explique ce qu'il fait). Voici le tableau final de la question initiale. J'ai ajouté ma propre idée en tant que deuxième colonne de formule.
New Table( "final?",Add Rows( 9 ),
New Column( "color",Character,"Nominal",
Set Values({"green", "green", "blue", "yellow", "red", "red", "yellow", "green", "green"})),
New Column( "count",Numeric,"Continuous",Format( "Best", 12 ),
Formula( Name Expr( Eval( Eval Expr( Col Sum( Row() <= Expr( Row() ), :color ) ) ) ) )),
New Column( "another count",Numeric,"Continuous",Format( "Best", 12 ),
Formula(
n = 0;
For( i = 1, i <= Row(), i++,
If( :color == :color[i], n++ )
);
n;
)
)
);
La formule de la troisième colonne pourrait être plus rapide, au détriment de la clarté, en la faisant regarder en arrière pour le dernier match et en ajoutant un à ce décompte. Clarté vs efficacité est un compromis.

Donc, je vais corriger le bogue découvert dans ce processus : lorsqu'une table de données crée un script pour se reproduire (comme l'exemple du haut), elle doit également produire du JSL pour reproduire les formules de colonne. Dans le cas où la formule de colonne commence par l'encapsuleur spécial eval( ) et que eval est censé faire partie de la formule, JMP doit ajouter le nom Expr.
mise à jour du 21 avril 2018 : répare la conversion automatique du blog précédent.