Ho già contattato il supporto JMP a riguardo e questo è stato contrassegnato come bug. Ecco un semplice caso "reale" in cui questo bug potrebbe essere visto
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
f2 = function({}, {Default Local},
Summarize(dt, uniq_values = by(:sex));
all_sex_values = dt[0, "sex"];
//dt = dt; // don't remove, it just works
For Each({uniq_value}, uniq_values,
cur_sex_rows = Loc(all_sex_values, uniq_value);
show(all_sex_values, uniq_value, cur_sex_rows, dt); // dt goes poof inside for each
vals = Transform Each({val}, dt[cur_sex_rows, "age"], Output("List"), Char(val));
show(vals);
);
);
f2();
all_sex_values = {"F", "F", "F", "F", "F", "M", "M", "M", "F", "F", "F", "M", "M", "M", "M", "F", "F", "F", "F", "F", "M", "M", "M", "M", "M", "M", "M", "F", "F", "M", "M", "M", "M", "M", "F", "F", "M", "F", "M", "M"};
uniq_value = "F";
cur_sex_rows = [1, 2, 3, 4, 5, 9, 10, 11, 16, 17, 18, 19, 20, 28, 29, 35, 36, 38];
dt = ␀;
argument value is invalid in access or evaluation of 'Transform Each' , Bad Argument(dt[cur_sex_rows, "age"]), Transform Each/*###*/({val}, dt[cur_sex_rows, "age"], Output("List"), Char(val))
at line 15 in mypath
Stavo lavorando su uno script in cui devo crittografarne una piccola parte, quindi ho racchiuso la maggior parte del codice da crittografare all'interno di una singola funzione per ridurre al minimo la possibilità che le mie variabili fuoriescano (sono pigro così in questo caso ). Durante la scrittura di questa singola funzione eccessivamente grande, ho notato che ricevevo errori "il valore dell'argomento non è valido" all'interno del mio ciclo For Each anche se tutte le variabili erano definite. Ho fatto alcuni test e ho scoperto che per ciascuno (e per gli altri cicli ciascuno) non gestivamo correttamente Default Local (o sembrava così). Di seguito sono riportati due esempi
Names Default To Here(1);
thing = Expr(
Summarize(dt, uniq_values = by(:sex));
all_sex_values = dt[0, "sex"];
For Each({uniq_value}, uniq_values,
cur_sex_rows = Loc(all_sex_values, uniq_value);
vals = Transform Each({val}, dt[cur_sex_rows, "age"], Output("List"), Char(val));
show(vals);
);
);
f1 = function({}, {Default Local},
thing;
);
f2 = function({}, {Default Local},
Summarize(dt, uniq_values = by(:sex));
all_sex_values = dt[0, "sex"];
//dt = dt; // don't remove, it just works
For Each({uniq_value}, uniq_values,
cur_sex_rows = Loc(all_sex_values, uniq_value);
show(all_sex_values, uniq_value, cur_sex_rows, dt); // dt goes poof inside for each
vals = Transform Each({val}, dt[cur_sex_rows, "age"], Output("List"), Char(val));
show(vals);
);
);
f3 = function({}, {all_sex_values, cur_sex_rows},
Summarize(dt, uniq_values = by(:sex));
all_sex_values = dt[0, "sex"];
For Each({uniq_value}, uniq_values,
cur_sex_rows = Loc(all_sex_values, uniq_value);
vals = Transform Each({val}, dt[cur_sex_rows, "age"], Output("List"), Char(val));
show(vals);
);
);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
Print("Thing Expr");
Try(thing, show(exception_msg));
Print("\!NThing Expr inside Function");
Try(f1(), show(exception_msg));
Print("\!NThing Function Only default local");
Try(f2(), show(exception_msg));
Print("\!NThing Function Only local list");
Try(f3(), show(exception_msg));
Close(dt, no save);
Names Default To Here(1);
my_val = 1;
my_func1 = function({}, {Default Local},
show(my_val);
);
my_func2 = function({}, {Default Local},
my_func1();
);
my_func22 = function({}, {Default Local},
my_func2();
);
my_func222 = function({}, {Default Local},
my_func = function({}, {Default Local},
show(my_val);
);
my_func();
);
my_func3 = function({}, {Default Local},
my_func1(); // even this goes null
For Each({z}, {"b","c"}, show(my_val));
);
my_func1();
my_func2();
my_func22();
my_func222();
my_func3();
Sono (segretamente) orgoglioso di poter lasciare questo (per ora) alla mia sceneggiatura di produzione poiché non le ho ancora avute (ma sono stato d'aiuto e ho aggiunto lì almeno il numero del caso per me in futuro).
dt = dt; // don't remove, it just works (JMP Support Case 00075244)
Ho ricevuto una risposta in merito dal personale di supporto JMP che aveva contattato lo sviluppatore JMP:
Sembra una cattiva interazione tra Function Default Local e le funzioni Each. Ecco un test fallito:
ut test("EachLoop", "Default Local in Body Expr", Expr(
defloc = 5;
f = Function({}, {Default Local}, Transform Each({x}, 1::5, x*defloc));
ut assert that(Expr(f), [5 10 15 20 25])
));
Poiché defloc è un nome non qualificato che appare nel corpo della funzione, è contrassegnato come locale predefinito. Ciò significa che JMP crea automaticamente un locale se scriviamo nel simbolo. Tuttavia, leggendolo come nello script sopra, dovrebbe saltare il frame locale e passare al frame successivo e al successivo fino a Here e Global. Questo è il comportamento previsto e quello che ottieni se leggi defloc al di fuori della funzione Each. Ma, se leggi all'interno della funzione Each, questo processo si interrompe per qualche motivo. Forse perché la funzione Each introduce un altro frame stesso poiché può avere anche local.
dt = dt è una soluzione alternativa, così come evitare completamente Default Local.