이에 대해 이미 JMP 지원팀에 문의했는데 이는 버그로 표시되었습니다. 이 버그를 볼 수 있는 간단한 "실제" 사례는 다음과 같습니다.
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
저는 스크립트의 작은 부분을 암호화해야 하는 스크립트를 작업하고 있었기 때문에 암호화해야 하는 대부분의 코드를 단일 함수 내부에 래핑하여 변수가 누출될 가능성을 최소화했습니다(이 경우에는 게으릅니다). ). 지나치게 큰 이 단일 함수를 작성하는 동안 모든 변수가 정의되었음에도 불구하고 For Each 루프 내에서 "인수 값이 잘못되었습니다" 오류가 발생하는 것을 발견했습니다. 나는 몇 가지 테스트를 수행한 후 각각(및 다른 각 루프)이 기본 로컬을 올바르게 처리하지 않는다는 것을 알아냈습니다(또는 그렇게 보였습니다). 아래에는 두 가지 예가 있습니다.
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();
나는 아직 그것을 가지고 있지 않았기 때문에 이것을 (지금은) 내 프로덕션 스크립트에 맡길 수 있다는 것을 (은밀하게) 자랑스럽게 생각합니다. (그러나 나는 도움이 되었고 미래를 위해 최소한 사례 번호를 거기에 추가했습니다.)
dt = dt; // don't remove, it just works (JMP Support Case 00075244)
JMP 개발자에게 연락한 JMP 지원 담당자로부터 이에 대한 답변을 받았습니다.
이는 Function Default Local과 Each 함수 간의 잘못된 상호 작용처럼 보입니다. 다음은 실패한 테스트입니다.
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])
));
defloc은 함수 본문에 나타나는 비정규 이름이므로 기본 로컬로 표시됩니다. 이는 기호에 쓰면 JMP가 자동으로 로컬을 생성한다는 의미입니다. 다만, 위 스크립트처럼 읽어올 때에는 로컬 프레임을 건너뛰고 다음 프레임으로 올라가서 Here와 Global까지 올라가야 합니다. 이는 예상되는 동작이며 Each 함수 외부에서 defloc을 읽으면 얻을 수 있는 동작입니다. 그러나 Each 함수 내부를 읽으면 어떤 이유로 이 프로세스가 중단됩니다. 아마도 Each 함수는 로컬을 가질 수 있기 때문에 다른 프레임 자체를 도입하기 때문일 것입니다.
dt = dt는 기본 로컬을 완전히 피하는 것과 마찬가지로 해결 방법입니다.