Al resolver la creación iterativa de columnas que contienen fórmulas, me encontré con la necesidad de estructurar la solución de una manera que no entiendo por qué. Mi solución inicial fue
Names Default To Here( 1 );
dt =
// Open Data Table: semiconductor capability.jmp
// → Data Table( "semiconductor capability" )
Open( "$SAMPLE_DATA/semiconductor capability.jmp" );
colNames = dt << get column names( continuous, string );
For Each( {col}, colNames,
theTarget = (Column( Eval( col ) ) << get property( "Spec Limits" ))["Target"];
Eval(
Eval Expr(
New Column( col || " Minus Target",
Numeric,
"Continuous",
Format( "Best", 10 ),
Formula( As Column( Eval( col ) ) - Expr( theTarget ) )
)
)
);
);
Y falla por
Column NPN1 Minus Target Formula Interrupted
Name Unresolved: col at row 1 in access or evaluation of 'col' , col/*###*/
Formula evaluation errors have been ignored
Column NPN1 Minus Target Formula Interrupted
Name Unresolved: col at row 1001 in access or evaluation of 'col' , col/*###*/
Formula evaluation errors have been ignored
Mientras que al forzar una asignación de la variable col el código funcionará
Names Default To Here( 1 );
dt =
// Open Data Table: semiconductor capability.jmp
// → Data Table( "semiconductor capability" )
Open( "$SAMPLE_DATA/semiconductor capability.jmp" );
colNames = dt << get column names( continuous, string )<BR /><BR />For Each( {xcol}, colNames,
col = xcol;
theTarget = (Column( Eval( col ) ) << get property( "Spec Limits" ))["Target"];
Eval(
Eval Expr(
New Column( col || " Minus Target",
Numeric,
"Continuous",
Format( "Best", 10 ),
Formula( As Column( Eval( col ) ) - Expr( theTarget ) )
)
)
);
);
Además, una vez que ejecuto el código con
col = xcol;
Puedo ejecutar el código sin la asignación xcol y el código original funcionará.
Esto me confunde. ¿Alguien puede explicar el razonamiento detrás de esto?
Lo más probable es que alguien de JMP tenga que dar la respuesta correcta. @EvanMcCorkle ?
No estoy seguro de la razón exacta, pero una razón es que la columna no se evaluará dentro de la fórmula ( cambie Eval() a Expr() para forzar el nombre de la columna dentro de As Column()) (O creo que puede ejecutar << ejecutar fórmulas después de la creación de la fórmula y luego eliminar la fórmula inmediatamente para asegurarse de que no se vuelva a evaluar con una columna incorrecta).
Si col es la variable que almacena para los valores de cada contenedor, no existirá fuera del bucle con esos valores (establecer xcol en col evita esto de alguna manera)
Names Default To Here(1);
a = {"a", "b", "c"};
b = "z";
show(b);
For Each({b}, a,
show(b);
);
show(b);
/*
b = "z";
b = "a";
b = "b";
b = "c";
b = "z";
*/
Prefiero usar este método (Expr(NameExpr(AsColumn())) ya que esto deja la fórmula "más limpia" (:nombre en lugar de AsColumn("nombre").
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/semiconductor capability.jmp");
colNames = (dt << get column names(continuous, string))[1::10];
For Each({col}, colNames,
theTarget = (Column(Eval(col)) << get property("Spec Limits"))["Target"];
Eval(
Eval Expr(
New Column(col || " Minus Target",
Numeric,
"Continuous",
Format("Best", 10),
Formula(Expr(NameExpr(As Column(col))) - Expr(theTarget))
)
)
);
);
Lo más probable es que no se trate del mismo problema que... Cada bucle tiene el alcance local de la función (esto es extremadamente molesto... Cada bucle no se comporta correctamente con el alcance local de la función. He informado de esto al soporte de JMP)
Names Default To Here(1);
b = 2;
my_f = function({a}, {Default Local},
c = Transform Each({item}, a,
a * b
);
return(c);
);
my_f2 = function({a}, {Default Local},
b = b; // "Fix"
c = Transform Each({item}, a,
a * b
);
return(c);
);
Try(
show(my_f({1,2,3}));
,
show(exception_msg);
);
Try(
show(my_f2({1,2,3}));
,
show(exception_msg);
);