스크립터는 JSL 함수나 메시지에서 변수를 인수로 사용하려고 하지만 예상한 결과를 얻지 못할 때 종종 혼란스러워합니다. 스크립터가 이런 상황에 직면하는 JSL의 상황은 많지만, 사용자가 자주 마주치는 상황은 Spec Limits 열 속성을 설정하려고 할 때입니다. Spec Limits로 사용할 값은 종종 이전 단계의 조회 테이블에서 추출되어 변수에 할당됩니다. 모든 제한 값을 수집하여 변수에 할당한 후 다음 논리적 단계는 이러한 변수를 사용하여 분석 테이블에서 열 속성을 설정하는 것입니다. 스크립터가 시도할 수 있는 대표적인 예는 다음과 같습니다. 이 JSL을 스크립팅 창에 복사하여 실행하면 따라할 수 있습니다.
Names Default to Here(1);
dt = Open("$SAMPLE_DATA/Cleansing.jmp");
myLSL = 6;
myUSL = 8;
myTarget = 7;
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( myLSL ), USL( myUSL ), Target( myTarget ), Show Limits( 1 )}
);
이 스크립트를 실행하면 pH 열 옆에 열 속성이 설정되었음을 나타내는 아이콘이 나타나고, 아이콘을 클릭하면 해당 속성이 Spec Limits 속성임을 확인할 수 있습니다.

하지만 사양 제한 값을 확인하기 위해 열 정보 대화 상자 창을 열면 해당 값이 누락되어 있습니다!

JMP는 무엇을 했나요? 효과가 있는 듯했지만, 부분적으로만! 왜?!?
조사하기 위해 JSL을 사용하여 속성 설정을 볼 수 있습니다. 이렇게 하면 단서를 얻을 수 있을 것입니다. 다음 표현식을 평가하면,
Column(dt, "pH") << Get Property("Spec Limits");
로그에 다음 정보가 기록됩니다.
{LSL( myLSL ), USL( myUSL ), Target( myTarget ), Show Limits( 1 )}
글쎄요, 정확히 제가 지정한 내용인데, 왜 변수 자체가 아니라 변수에 할당된 값이 보이지 않을까요? 이 질문에 대한 답은 혼란의 핵심에 도달합니다. JSL은 항상 할당된 값을 확인하기에 충분한 횟수로 인수를 평가하지 않으며, 인수가 평가되는 횟수는 변수가 사용되는 상황에 따라 다릅니다. 예를 들어, 현재 컨텍스트에서 JMP는 Spec Limits 속성의 다양한 측면을 지정하는 항목이 있음을 이해하기 위해 목록 인수를 "구문 분석"합니다. 이는 하나의 평가입니다. 다른 평가에서 JMP는 목록의 항목을 검토하여 Spec Limits 속성에 설정할 제한(LSL, USL, Target 등)을 결정합니다. JMP는 목록 항목 내부에 제공된 인수(myLSL, myUSL, myTarget)를 전혀 평가하지 않습니다. JMP는 LSL, USL 및 Target에 대한 인수로 숫자 값을 예상합니다. 변수가 제공되면 JMP는 이를 인식하지 못하고 연관된 값을 확인하기 위해 변수를 확인하려고 하지 않습니다.
그렇다면 주어진 상황에서 인수가 몇 번 평가될지 알 수 있을까요? 위의 예처럼 더 많은 평가가 필요한 경우 어떻게 해야 할까요? JMP의 소스 코드에 액세스할 수 없기 때문에 주어진 상황에서 몇 번의 평가가 수행될지 아는 것은 매우 어렵습니다. 그러나 그것은 현재 사용에 충분한 지 아는 것보다 덜 중요합니다. 제가 하는 첫 번째 일은 시도하고 확인하는 것입니다!
Spec Limits 메시지가 값을 어떻게 기대하는지에 대한 사전 지식이 없이, 저는 처음에 위에 표시된 대로 스크립트를 정확히 작성합니다. 다음으로, 열 정보 대화 상자에서 Spec Limit을 검토하거나 열이 있는 그래프를 만들어 그래프 참조선이 제대로 표시되는지 확인하여 Spec Limit이 설정되었는지 확인합니다. 이 경우처럼 검증이 실패하면 표현식을 편집하여 변수를 제거하고 대신 숫자 값을 하드 코딩해야 합니다.
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
그런 다음 표현식을 실행하여 문제가 변수 사용에 있고 다른 구문 문제가 아닌지 확인합니다. 표현식이 하드코딩된 값으로 예상 결과를 제공하는지 확인한 후, 변수가 할당된 값에 도달하기에 충분히 평가되지 않는 상황에 직면했다는 것을 알게 되었습니다. 따라서 표현식을 평가하기 전에 변수 값을 임베드하기 위해 JMP에서 런타임에 표현식을 동적으로 생성해야 합니다.
변수를 미리 평가하는 방법은 여러 가지가 있지만, 제가 선호하는 방법은 Eval Expr() 함수를 사용하는 것입니다. 다른 방법으로는 Substitute() 함수를 사용하거나 문자열을 연결하여 JSL 표현식을 빌드한 다음 최종 문자열을 구문 분석하고 평가하는 방법이 있습니다. 제가 가장 싫어하는 방법은 표현식을 문자열로 빌드하는 것입니다. 이 코드는 단색이기 때문에 읽기가 매우 어려워서 JSL 편집기에서 제공하는 유용한 의미적 서식을 잃고 포함된 따옴표를 이스케이프해야 합니다. 더 나쁜 것은 선택한 코드 부분을 평가할 수 없기 때문에 코드를 디버깅하고 문제를 해결하기 어렵다는 것입니다.
Parse(
"Column( dt, \!"pH\!" ) << Set Property(
\!"Spec Limits\!",
{LSL( " || Char(myLSL) || " ), USL( " || Char(myUSL) || " ), Target( " || Char(myTarget) || " ), Show Limits( 1 )}
)"
)
이런 측면에서는 Substitute() 함수를 사용하는 것이 더 좋지만, 표현식이 길면 대체가 어디에서 수행되는지 지정하는 후반 인수를 보면서 표현식을 읽는 것이 어렵습니다.
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
)
이와 대조적으로, Eval Expr() 함수는 인라인 대체 지정을 허용하며, 함수의 인수가 표현식이므로 JSL 편집기는 이를 의미적 서식과 함께 표시할 수 있습니다.
그렇다면 Eval Expr()은 어떻게 작동할까요? 이것은 표현식을 유일한 인수로 취하고 표현식을 반환하는 함수입니다. 제공된 표현식에서 Expr() 토큰을 검색합니다. 그런 다음 JMP는 Expr()의 괄호 안에 있는 내용을 평가하고 전체 토큰을 반환 값으로 바꿉니다. 위의 예로 돌아가 사양 제한을 설정하면, 변수를 Expr()로 "래핑"하고 전체 표현식을 Eval Expr() 호출 내에 배치하면 JMP는 런타임에 변수(및 Expr() 토큰)를 변수 값으로 대체하고 수정된 표현식을 반환합니다. 따라서,
Eval Expr(
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( Expr(myLSL) ), USL( Expr(myUSL) ), Target( Expr(myTarget) ), Show Limits( 1 )} );
);
보고:
Column( dt, "pH" ) << Set Property(
"Spec Limits",
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
)
훌륭합니다! 이제 원하는 하드코딩된 값을 포함하는 Spec Limits 속성을 설정하는 표현식이 있습니다. 방금 JSL 코드를 동적으로 작성했습니다! 이제 이 수정된 표현식을 평가하기만 하면 됩니다. 이를 위해 Eval() 함수가 유용합니다. Eval Expr()을 래핑하고 Eval() 호출을 호출하면 Eval Expr()에서 반환된 표현식이 즉시 평가됩니다. 다음은 런타임에만 알려진 제한 값을 사용하여 Spec Limits 속성을 올바르게 설정하는 완전한 예제 스크립트입니다.
Names Default to Here(1);
dt = Open("$SAMPLE_DATA/Cleansing.jmp");
myLSL = 6;
myUSL = 8;
myTarget = 7;
Eval(Eval Expr(
Column(dt, "pH") << Set Property(
"Spec Limits",
{LSL( Expr(myLSL) ), USL( Expr(myUSL) ), Target( Expr(myTarget) ), Show Limits( 1 )}
);
));
이제 이 스크립트를 검증하면 열 정보 대화 상자에서 사양 제한에 대한 값을 볼 수 있습니다.

또한 이 표현을 평가하면
Column(dt, "pH") << Get Property("Spec Limits");
로그에 다음 정보가 기록됩니다.
{LSL( 6 ), USL( 8 ), Target( 7 ), Show Limits( 1 )}
마지막으로 해당 열을 사용하여 그래프를 생성하면 예상된 위치에 사양 제한 참조선이 표시됩니다.

JSL 코드를 동적으로 작성하는 것은 스크립터가 개발하기에 유용한 기술입니다. JMP가 표현식의 인수를 필요한 실제 값에 도달할 만큼 충분히 평가하지 않는 상황이 많이 있습니다. JSL 코드를 동적으로 작성하는 데는 여러 가지 기술이 있지만, 제가 선호하는 방법은 Eval(EvalExpr(Expr())) 메서드입니다. 이 메서드는 인라인 대체 및 의미적 서식 지정을 허용하여 코드를 읽고 디버깅하는 것을 비교적 쉽게 만듭니다.