JSL 도움말: Set Function() 명령 구문 도움말안녕하세요 여러분,
또 다른 JSL 프로그래밍 질문으로 돌아갑니다. 예를 들어 다른 게시물과 관련이 있습니다. 여기 .
확인란을 선택하면(상태=1) 선택한 행(RSquare가 음수인 행)이 선택된 다음 숨겨지고 제거되어 업데이트된 그래프 빌더가 실행되는 Check Box() 기능을 갖고 싶습니다. 원하는 출력을 보여줍니다. 그런 다음 상자가 선택 취소된 경우(상태=0) 해당 행을 숨기기 취소 및 제외 취소합니다. 내가 사용하고 있는 Set Function() 호출은 아래와 같습니다. Set Function()의 "스크립트"를 수동으로 실행하면 작동하지만 자동으로 수행되지는 않습니다. 자동으로 업데이트하기 위해 내가 누락된 것이 무엇인지 알 수 없습니다. 좋은 글 발견했어요 여기 , 그리고 나는 하려고 노력 중이야 무엇 이 사람이 한 것과 비슷하지만 그래프 빌더 업데이트를 위한 것입니다.
JSL 설정 함수 호출:
cb << Set Function(<BR />{this},<BR />this = cb << Get;<BR />If(<BR />this == 1,<BR />dt_results << Select Rows( neg_rows ) << Hide and Exclude;<BR />dt_results << Clear Select;<BR />dt_tb = dt_results << Get As Report();,<BR />this == 0,<BR />dt_results << Select Rows( neg_rows ) << Unhide;<BR />dt_results << Select Rows( neg_rows ) << Unexclude;<BR />dt_results << Clear Select;<BR />dt_tb = dt_results << Get As Report()<BR />);<BR />);cb << Set Function(
{this},
this = cb << Get;
If(
this == 1,
dt_results << Select Rows( neg_rows ) << Hide and Exclude;
dt_results << Clear Select;,
this == 0,
dt_results << Select Rows( neg_rows ) << Unhide;
dt_results << Select Rows( neg_rows ) << Unexclude;
dt_results << Clear Select;
);
);여기서 cb는 코드 앞부분에서 다음과 같이 참조됩니다.
cb = Check Box( "Remove bad points (*'s)?", <<SET></SET>
출력 시작 또는 확인란이 상태 = 0일 때마다:

확인란이 상태 = 1일 때마다 원하는 출력:

제외된 행이 오른쪽 보고서 보기에서 제거되도록 데이터 테이블을 오른쪽 보고서로 업데이트하면 좋을 것 같지만 생각보다 훨씬 어려울 수 있습니다. Set Function() 명령에 추가 Get As Report 업데이트를 추가하려고 시도했지만 아무 작업도 수행되지 않습니다.
모든 의견을 보내주시면 감사하겠습니다.
DS
데이터 혼합 및 정리Re: JSL 도움말: Set Function() 명령 구문 도움말나는 일상 업무에서 정반대의 문제에 더 많이 직면합니다.
아님: 동일한 네임스페이스를 공유하는 2개의 창
하지만: 가끔 *) 공통을 공유하는 2개의 스크립트 여기 네임스페이스.
하나의 JSL 파일을 다른 파일에 포함시키면, 런타임 시 , 포함된 스크립트는 여기 기본 jsl 파일의 네임스페이스입니다.
하지만 일부 코드 줄을 디버깅하고 두 번째 스크립트에서 실행하고 싶을 때 포함된 코드를 어떻게 제공할 수 있습니까? 스크립트_B 에 대한 액세스 여기 메인 스크립트의 네임스페이스? 2초 전에 script_B의 코드를 실행했을 때 해당 네임스페이스에 대한 액세스 권한만 있었습니다.
https://community.jmp.com/t5/Discussions/Debugging-Jmp-applications/mp/701121/highlight/true#M88566
Re: JSL 도움말: Set Function() 명령 구문 도움말감사하다, @ErraticAttack Jmp에서 범위 지정이 어떻게 작동하는지 아름다운 예를 들어보세요.
이해하는데 많은 도움이 되었습니다..
지금까지 나는 무엇을 이해할 수 없었습니다. @drewfoglia ~와 함께라는 의미

~에 효율성과 재현성을 위한 필수 스크립팅: 적은 작업으로 더 많은 작업을 수행(2019-US-TUT-290)
당신의 예는 이것이 사실이 아님을 잘 보여줍니다.
여기서 우리의 경험이 Drew의 진술과 다른 이유는 무엇입니까?
동일한 JSL 편집기 창에서 창이 생성되었기 때문인 것 같습니다.
첫 번째 TEST 창을 연 후에도 스크립트 창이 참조된 개체에 계속 액세스할 수 있다는 점은 매우 유용합니다. 테브 그리고 결핵 .
두 번째 TEST 창을 연 후, 테브 그리고 결핵 이제 두 번째 창의 개체를 참조하십시오. 이는 분명히 첫 번째 창의 기능을 손상시킵니다(입력된 텍스트는 결핵 , 즉 두 번째 창에서).
따라서 boh 주장을 연결하면 두 Windows가 공통 JSL 편집기를 공유하지 않으면 어떻게 될까요?
-> 둘 다 Drew가 강연에서 발표한 것처럼 독립적인 NameSpace를 갖게 됩니다.
이를 위한 옵션:
a) 스크립트를 닫고 다시 연 다음 두 번째 창을 만듭니다.
b) 메뉴에서 스크립트를 호출합니다.

Re: JSL 도움말: Set Function() 명령 구문 도움말안녕 @ErraticAttack ,
답변과 상세한 글 감사드립니다. 제가 전문 프로그래머가 아니기 때문에 이 문제를 해결하는 데는 시간이 좀 걸릴 것입니다. 이 중 많은 부분이 아직 저에게는 새로운 것입니다.
감사해요!,
DS
Re: JSL 도움말: Set Function() 명령 구문 도움말@ih 예를 들어, JMP가 예상한 대로 범위 지정을 수행하지 않는 경우(특히 Python에서 오는 경우) 이 스크립트에서 창 두 개를 실행하기만 하면 됩니다. 이름은 첫 번째 창에 연결되지 않고 두 번째 창에만 연결됩니다.이것이 범위 지정과 관련하여 사람들이 겪는 가장 큰 문제입니다(그러나 유일한 문제는 아닙니다).JMP는 window: 네임스페이스와 같은 몇 가지 편리한 의사 네임스페이스를 제공합니다.그러나 이는 적절한 네임스페이스 변수가 아니며 대규모 스크립트에서는 예상대로 완전히 작동하지 않습니다.
Names Default to Here( 1 );
New Window( "TEST",
V List box(
teb = Text Edit Box( "", <<SET hint=""></SET>
@SDF1 , 명시적인 네임스페이스 범위 지정을 위해 내가 한 일은 메타 프로그래밍을 통해 지루한 범위 삽입 작업을 모두 수행하는 라이브러리를 만드는 것입니다.이는 Python에서 작동하는 것과 거의 동일하게 클래스를 정의할 수 있다는 추가 이점이 있습니다(편리한 조회 재정의 제외).회사 업무의 일부이기 때문에 라이브러리를 공유할 수는 없지만 본질적으로 다음과 같은 일이 일어나고 있습니다.
다음과 같은 간단한 스크립트가 있다고 가정해 보겠습니다.
Names Default to Here( 1 );
/*
Doing something initialization here!!
*/
dt = Current Data Table();
New Window( "Super Useful Script",
,
<<ON close=""></ON>
이 스크립트에는 두 개의 대화형 UI 요소, 일부 초기화 및 잠재적으로 창 닫기 시 일부 정리가 포함되어 있습니다.개념적으로 디스플레이 트리와 로직은 혼합되어 있으며 매우 깊은 블록이 있습니다.개념적으로 구별되는 요소가 코드 내에서도 구별되면 코드가 더 보기 좋고 유지 관리가 더 쉽습니다.간단하게 제목과 호출할 함수 이름을 넣어 버튼박스를 만들어주면 좋을 것 같습니다.호출하는 함수는 최상위 함수(스크립트의 어느 부분에서나 쉽게 호출할 수 있음)가 되며 표시 트리와 분리됩니다.
이것을 다음과 같이 소화하고 작업하기 _훨씬_ 더 쉬운 것으로 변환할 수 있습니다:
/* super useful script */
initialize = Function( {}, // entry point to script
/* perform any initialization needed here */
self:dt = Current Data Table();
1
);
content = Function( {}, // this holds the display tree
V List Box(
self:one click button = meta:Button Box( "Useful 1-click function", "call one click" )
,
H List Box(
self:value teb = meta:Text Edit Box( "", "handle value change" ) << Set Hint( "Enter Value" )
)
)
);
finalize = Function( {}, // called after display tree has finalized
1
);
on close = Function( {}, // called when window wants to close
1
);
call one click = Function( {}, // called when button is pressed (line 11)
Print( "Done" )
);
handle value change = Function( {}, // called when TEB value changes(line 14)
Print( "Doing something special" )
);이제 일반 JSL 실행 스크립트 버튼을 누르면 이 스크립트는 많은 작업을 수행하지 않습니다.이를 위해 수행해야 할 작업은 먼저 메타 네임스페이스(나머지 스크립트와 잘 연결될 수 있도록 ButtonBox 및 TextBox 래퍼를 보유함)를 정의하고 다음을 수행하는 메타 프로그래밍 래퍼 함수를 정의하는 것입니다.
다음과 같은 프로토타입 스크립트를 작성해 보세요.
<SOME script="" is="" above="" me="">
do someting = Function( {},
...
);
finalize = Function( {},
...
);
<MORE script="" is="" below="" me=""></MORE></SOME>다음 프로토타입으로 변환합니다.
<SOME script="" is="" above="" me="">
self:do someting = Function( {},
self = Namespace( "#434" );
...
);
self:finalize = Function( {},
self = Namespace( "#434" );
...
);
<MORE script="" is="" below="" me=""></MORE></SOME>
이 메타 프로그래밍 함수는 `self`를 단순히 `self = New Namespace()`로 정의한 다음 위와 같이 각 함수에 자체 정의를 삽입합니다(물론 "#434"는 매번 달라집니다).스크립트를 다시 작성한 후 다음을 수행하십시오. (이 내용은 내 라이브러리에서 거의 정확하게 가져온 것입니다.)
If( self << Contains( "initialize" ), Try( self:initialize(), Print( "Error with self:initialize" ); Show( exception_msg ); ); );
Eval(
Substitute(
Expr(
self:window = New Window( self:tool name,
<<ON close="">>" ) );
Try(
self:finalize
,
Print( "Error with self:finalize" );
Show( exception_msg );
);</ON>
다음은 내 스크립트에 있는 실제 예입니다.메타 프로그래밍 전 입력은 다음과 같습니다.
tool name = "Example";
initialize = Function( {},
{Default Local},
Show( "initialized" )
);
content = Function( {},
H List Box(
meta:Button Box( "Hello World", "run" )
,
self:n days box = meta:Number Edit Box( 30, "run" )
)
);
run = Function( {},
{var1, var2},
Show( "running" )
);
finalize = Function( {},
Show( "finalized" );
show( self:n days box << Get );
);
0;스크립트를 평가하기 직전(메타 프로그래밍 단계 이후)은 다음과 같습니다.
self:tool name = "Example";
self:initialize = Function( {},
{Default Local},
self = Namespace( "#58" );
Show( "initialized" );
);
self:content = Function( {},
{self, this},
self = Namespace( "#58" );
H List Box(
meta:Button Box( "Hello World", "run" )
,
self:n days box = meta:Number Edit Box( 30, "run" )
);
);
self:run = Function( {},
{var1, var2, self, this},
self = Namespace( "#58" );
Show( "running" );
);
self:finalize = Function( {},
{self, this},
self = Namespace( "#58" );
Show( "finalized" );
Show( self:n days box << Get );
);
0;요약하자면, 메타 프로그래밍에는 어떤 것이든 필요합니다. 우스코프된 최상위 변수로 명시적으로 범위를 `self`로 지정합니다.그런 다음 최상위 함수를 가져와 첫 번째 줄(`self = Namespace( )`)을 추가합니다.이것은 개념적으로 매우 간단하며 JSL을 사용하면 구현하기가 매우 쉽습니다.불행하게도 `Function()` 함수의 형식에 따라 여러 분기가 있습니다(인수가 2개인지 3개인지, 두 번째 인수가 {Default Local}인지 아니면 단순히 지역 변수 목록인지).
그렇다면 이 모든 메타 프로그래밍이 당신에게 무엇을 가져다 줄까요?아래와 같이 동등한 작업을 수행하지 않기 위해서입니다.아래 스크립트는 대부분 Eval( Eval Expr( ... ) ) 문으로 래핑되어 있습니다.이렇게 하면 기능 내에서 이러한 명령문을 사용할 수 없으므로 대규모 프로젝트에는 적합하지 않습니다.또한 디스플레이 트리에는 여전히 보기 흉한 보일러 플레이트가 있습니다( < ) ... ) ) 블록은 크고 보기 흉합니다)
self = New Namespace();
self:tool name = "Example";
Eval( Eval Expr(
self:initialize = Function( {},
{Default Local},
self = Namespace( Expr( self << Get Name ) );
Show( "initialized" )
);
self:content = Function( {},
self = Namespace( Expr( self << Get Name ) );
H List Box(
Button Box( "Hello World",
<<SET function="">>" ) );
Try(
self:finalize
,
Print( "Error with self:finalize" );
Show( exception_msg );
);</SET>이 스크립트에는 많은 상용구가 포함되어 있지만 보다 명시적인 범위 제어를 원할 때 필요합니다.특히, 사용자에게 "한 번에 하나의 창만 열어라!"라고 말하고 싶지 않은 경우.메타 프로그래밍 단계를 만드는 것은 약간 지루하고 확실히 많은 학습이 필요하지만 일단 이해하고 나면 매우 보람 있고 훨씬 더 간결하고 유지 관리 가능한 코드를 허용합니다.
여기서 제가 보여드린 것은 매우 잘 작동하고 대화형 UI 생성을 쉽게 만드는 클래스(JMP14+ NewObject 클래스와 완전히 별개)를 생성하는 기능입니다.
나는 이것이 많은 일이라는 것을 알고 있습니다(그리고 더 중요한 점은 UI 스크립트를 작성하는 초기 접근 방식과는 거리가 멀다는 것입니다). 그러나 하나 또는 두 개 이상의 작은 UI 스크립트를 작성하는 경우 메타 프로그래밍을 작성하는 데 시간이 걸립니다. 래퍼(한 번만 수행하면 됨)는 빠르게 가치가 있을 것입니다.
Re: JSL 도움말: Set Function() 명령 구문 도움말안녕 @ErraticAttack ,
피드백을 보내주셔서 감사합니다. 나는 당신이 나에게 Namespace()를 추천한 것이 이번이 두 번째라는 것을 알았습니다 ;-).
결과적으로 저는 지난 하루 반 동안 스크립팅 가이드에서 NameSpace를 사용하는 방법을 읽었습니다. 이는 스크립팅 인덱스보다 낫지만 여전히 사용 방법과 같은 최상의 예를 제공하지는 않습니다.네임스페이스를 사용하는 방식에 있어 JMP 14 스크립팅 가이드나 스크립팅 인덱스보다 더 나은 입문서가 있습니까?
나는 당신이 하고 있는 일을 제대로 따라갈 수 없으며 더 잘 배워야 한다는 것을 인정해야 합니다. 그러나 여기에 있는 귀하의 게시물과 다른 게시물 중 하나에 제공한 예제 코드를 기반으로 합니다. 여기 , Namespace()를 사용하여 첫 번째 창을 호출하는 스크립트 섹션을 다시 작성할 수 있었습니다. 그러나 나는 그다지 훌륭하지 않은 스크립팅 기술을 통해 작업할 수 있다는 것을 후속 창과 디스플레이에서 어떻게 스크립팅할지 잘 모르겠습니다. 제가 하고 싶은 프로그래밍 방식으로 전환하기 전에 네임스페이스를 올바르게 사용하는 방법을 배우는 데는 시간이 좀 걸릴 것 같습니다.
부정적인 데이터(이 경우 의미 없음)를 숨기거나 제외하기 위해 상자를 선택/선택 취소할 때 디스플레이의 그래프 빌더를 업데이트할 수 있었습니다. 아래 스크립트는 내가 원하는 작업을 수행하지만(특정 데이터가 그래프에서 제거될 때 테이블 상자를 업데이트하는 경우 제외) 프로그래밍 관점에서 이상적이지 않다는 것을 이해합니다.
감사해요!,
DS
Names Default To Here( 1 );
lbWidth = 168;
dt = Open( "$SAMPLE_DATA/Boston Housing.jmp" );
// Expression to store the current settings in global variables
recallRolesS1 = Expr(
::dtchosenRecall = dtchosen
);
// Expression to clear all current settings. KW: Clear
clearRoles = Expr(
Try(
colListY << RemoveAll;
ColListX << RemoveAll;
ColListW << RemoveAll;
ColListF << RemoveAll;
colListV << RemoveAll;
)
);
// Expression to store the current settings in global variables
recallRoles = Expr(
::ycolRecall = colListY << GetItems;
::xcolRecall = colListX << GetItems;
::WcolRecall = colListW << GetItems;
::FcolRecall = colListF << GetItems;
::vcolRecall = colListV << GetItems;
::max_spRecall = max_sp_input << get;
::partVPRecall = partVP_input << Get;
);
//Function to choose the data table to model. KW: choose_data
choose_data_table = Function( {},
list = {};
For( i = 1, i <= N Table(), i++,
list[i] = Data Table( i ) << get name
);
win = New Window( "Select a data table",
<<MODAL> Training R².",
<<SET font="" size=""> 1, Throw( "Too many items selected!\!rOnly one selection possible." ),
N Items( SelRows ) == 1,
SelRows = this << Get Selected Rows;
NPCs = SelRows[1];
);
dt_results << Clear Select;
dt_results << Select rows( SelRows );
)
);
);
Part = Expr(
If(
N Items( vcols ) == 1,
dt_results = New Table( "Partition_Results",
Add Rows( max_sp ),
New Column( "Splits", Numeric, Continuous ),
New Column( "Training RSquare", Numeric, Continuous ),
New Column( "Validation RSquare", Numeric, Continuous ),
New Column( "Training RASE", Numeric, Continuous ),
New Column( "Validation RASE", Numeric, Continuous ),
New Column( "RSquare Diff", Numeric, Continuous, Formula( "Training RSquare"n - "Validation RSquare"n ) ),
New Column( "Penalized Valid RSquare", Numeric, Continuous, Formula( "Training RSquare"n - 0.05 * "Splits"n ) ),
New Column( "Training N", Numeric, Continuous ),
New Column( "Validation N", Numeric, Continuous )
),
N Items( vcols ) == 0 & Is Missing( partVP ) == 0,
dt_results = New Table( "Partition_Results",
Add Rows( max_sp ),
New Column( "Splits", Numeric, Continuous ),
New Column( "Training RSquare", Numeric, Continuous ),
New Column( "Validation RSquare", Numeric, Continuous ),
New Column( "Training RASE", Numeric, Continuous ),
New Column( "Validation RASE", Numeric, Continuous ),
New Column( "RSquare Diff", Numeric, Continuous, Formula( "Training RSquare"n - "Validation RSquare"n ) ),
New Column( "Penalized Valid RSquare", Numeric, Continuous, Formula( "Validation RSquare"n - 0.05 * "Splits"n ) ),
New Column( "Training N", Numeric, Continuous ),
New Column( "Validation N", Numeric, Continuous )
),
N Items( vcols ) == 0,
dt_results = New Table( "Partition_Results",
Add Rows( max_sp ),
New Column( "Splits", Numeric, Continuous ),
New Column( "Training RSquare", Numeric, Continuous ),
New Column( "Training RASE", Numeric, Continuous ),
New Column( "Penalized Train RSquare", Numeric, Continuous, Formula( "Training RSquare"n - 0.05 * "Splits"n ) ),
New Column( "Training N", Numeric, Continuous )
)
);
For( i = 1, i <= max_sp, i++,
dt_results:"Splits"n[i] = i
);
dt_name = dtchosen << Get Name;
For( i = 1, i <= N Rows( dt_results ), i++,
Psplit = dt_results:"Splits"n[i];
str = Eval Insert(
"report = (dtchosen<<PARTITION></PARTITION></SET></MODAL>Re: JSL 도움말: Set Function() 명령 구문 도움말안녕 @ErraticAttack ,
내 경험에 따르면 변수 범위 지정은 일관됩니다. 직관적이지 않을 수도 있지만 저는 항상 예측 가능하다고 생각했습니다.불일치가 발생하는 경우 스크립팅 가이드를 자세히 살펴보고 다양한 기호의 범위가 어떻게 지정되는지 교차 확인하는 것이 좋습니다.
어떤 상황에서는 일반적으로 탐색적 분석이나 대화형으로 실행되는 스크립트의 경우 호출 컨텍스트 함수를 사용하여 함수 호출을 단순화하는 데 큰 성공을 거두었습니다. 예를 들어 로그 함수는 파일이나 창에 메시지를 보내고 매번 입력/복사/붙여넣기할 필요 없이 반복자 또는 단계 값을 포함할 수 있습니다.
Names default to here(1);
lg = function({msg},
write(msg || try(", i=" || char(i), "") || "\!N")
);
lg("starting loop");
local({i},for(i=1, i<= 5, i++, lg("done")))Re: JSL 도움말: Set Function() 명령 구문 도움말안녕 @pmroz ,
의견을 보내 주셔서 감사합니다. 나는 현재 창을 업데이트하고 새 창을 만들지 않으려고 했습니다. Check Box()의 선택/선택 취소 상태를 업데이트하도록 그래프에 대한 작업을 수행할 수 있었습니다. 안타깝게도 데이터 테이블이 포함된 테이블 상자를 원하는 대로 업데이트할 보고서로 가져올 수 없습니다. 이 부분은 제가 생각했던 것보다 훨씬 더 복잡해 보이지만 실제로는 그다지 중요하지 않습니다. 그래픽 디스플레이가 예상대로 작동하도록 하는 것이 더 좋습니다. 그래도 테이블 상자가 업데이트되면 좋을 것 같습니다.
감사해요!,
DS
Re: JSL 도움말: Set Function() 명령 구문 도움말<
대부분 JSL에는 Python처럼 엄격한 범위 제어 기능이 없습니다.모든 유형의 복잡한 대화형 UI의 경우 여러 표시 요소 콜백에서 지속되어야 하는 모든 변수의 범위를 항상 명시적으로 지정해야 합니다.
또한 미적 및 실용적인 코드 형식을 모두 고려하여 아래와 같이 둘러싸는 울타리 수준에 항상 쉼표를 넣어야 합니다.이를 통해 코드 블록을 매우 빠르고 쉽게 시각적으로 이해할 수 있습니다.IF 문의 다양한 블록이 어디에 있는지 시각적으로 쉽게 표시할 수 있습니다.
마지막으로 NewWindow() 개체의 <
ns = <RELEVANT namespace="" with="" variables="" defined="" above="">
Eval( Eval Expr(
ns:cb << Set Function( {this},
ns = Namespace( Expr( ns << Get Name ) );
state = this << Get;
If(
state == 1,
ns:dt_results << Select Rows( ns:neg_rows ) << Hide and Exclude;
ns:dt_results << Clear Select;
,
state == 0,
ns:dt_results << Select Rows( ns:neg_rows ) << Unhide;
ns:dt_results << Select Rows( ns:neg_rows ) << Unexclude;
ns:dt_results << Clear Select;
);
);
) );</RELEVANT>Re: JSL 도움말: Set Function() 명령 구문 도움말다음과 같이 시도해 보십시오:
nw = new window("Test",
one_cb = checkbox({"Turn On"},
one_value = one_cb << Get;
If (one_value,
dt_results << Select Rows( neg_rows ) << Hide and Exclude;
dt_results << Clear Select;
dt_tb = dt_results << Get As Report();
// else
,
dt_results << Select Rows( neg_rows ) << Unhide;
dt_results << Select Rows( neg_rows ) << Unexclude;
dt_results << Clear Select;
dt_tb = dt_results << Get As Report()
);
)
);