모두,
다음 문제가 있습니다. 여러 테이블과 창을 열고 닫는 스크립트가 있으며 이를 처리하기 위해 여러 네임스페이스를 만듭니다. 또한 메인 창의 <
두 개의 스크립트 인스턴스가 실행 중일 때 그 중 하나에서 기본 창을 닫으면 네임스페이스가 삭제되고 다른 스크립트가 중단된다는 것을 알았습니다.
각 인스턴스에 대해 네임스페이스를 분리하려면 어떻게 합니까? 또는 스크립트\추가 기능의 한 인스턴스만 실행하도록 허용하려면 어떻게 합니까?
나는 그것을 이해한다.
ns = New Namespace();
ns 은 참조이며 네임스페이스가 생성될 때마다 할당되는 "#43"과 같은 고유한 이름이 있습니다. < ns 하나의 실행 중인 스크립트 인스턴스에서 "#43"을 참조하고 있으며, ns 실행 중인 다른 인스턴스에서 "#44"라고 가정해 보겠습니다.
응용 프로그램에 따라 다릅니다. 예를 들면 다음과 같습니다.
- 특정 창 이름이 존재하는지 확인
- 명명된 네임스페이스를 사용하고 이미 존재하는지 확인
그런 다음 존재하는지 여부에 따라 일부 작업을 수행합니다.
스크립팅 가이드 > 프로그래밍 방법 > 고급 범위 지정 및 네임스페이스(help, jmp.com) 꽤 잘 읽었습니다
Names Default To Here(1);
// Delete Namespaces()
ns1 = New Namespace("AA");
show(ns1);
ns1 = New Namespace();
ns3 = New Namespace();
show(Get Namespace Names());
show(ns1);
If(Contains(Get Namespace Names(), "AA"),
ns1 = Namespace("AA");
);
show(ns1);
If(Contains(Get Window List() << Get Window Title, "window_title"),
Window("window_title") << Bring Window To Front;
Throw("Window already exists...");
);JMP에서 적절한 범위 제어 및 리소스 관리를 수행하는 것은 까다로울 수 있습니다. -- JMP 개체 데이터 테이블() , 그리고 네임스페이스() 메모리에서 명시적으로만 해제되며 역참조에 의해 해제되지 않습니다.
내 목적을 위해 필요한 모든 범위 관리 및 리소스 제어를 처리할 수 있는 메타 프로그래밍 라이브러리를 만들었습니다(내 작업의 일부이므로 파일을 공유할 수 없습니다).
::modify display tree functions = Function( {self, display tree},
{Default Local},
box types = {"TextEditBox", "ButtonBox", "ListBoxBox"}; // Add others here
For( i = 1, i <= N Items( box types ), i++,
boxes = display tree << XPath( "//" || box types[i] );
For( j = 1, j <= N Items( boxes ), j++,
box = boxes[j];
function = Parse( Char( box << Get Function ) );
If( Try( Is Missing( function ), 0 ), Continue() ); // no function set
If( Head Name( function ) != "Function",
arg = Name Expr( function );
If( Head Name( arg ) != "Glue", // function is the right type -- a single call
new arg = Eval Expr( Glue( self = Namespace( Expr( self << Get Name ) ) ) );
Insert Into( new arg, Parse( "self:" || Char( Name Expr( arg ) ) ) );
Eval( Substitute( Expr(
box << Set Function( Local( {self}, __expr__ ) )
)
,
Expr( __expr__ ), Name Expr( new arg )
) )
)
,
arg = Arg( function, N Arg( function ) );
If( Head Name( arg ) != "Glue", // function is the right type -- a single call
new arg = Eval Expr( Glue( self = Namespace( Expr( self << Get Name ) ) ) );
Insert Into( new arg, Parse( "self:" || Char( Name Expr( arg ) ) ) );
Eval( Substitute( Expr(
box << Set Function(
Function( __args__,
{self},
__expr__
)
)
),
Expr( __args__ ), Arg( function, 1 )
,
Expr( __expr__ ), Name Expr( new arg )
) )
)
);
)
)
);
::inject self namespace = Function( {script},
{Default Local},
self = New Namespace();
script = Arg( script, 1 );
windows = {};
For( i = 1, i <= N Arg( script ), i++,
arg i = Arg( script, i );
If( Head Name( arg i ) == "Assign",
Remove From( script, i );
Insert Into( script,
Substitute(
Expr( Assign( _a_, _b_ ) )
,
Expr( _a_ ), Parse( "self:" || Char( Arg( arg i, 1 ) ) )
,
Expr( _b_ ), Arg( arg i, 2 )
)
,
i
);
arg i = Arg( script, i )
);
If( Head Name( arg i ) == "Assign" & As Name( Head Name( Arg( arg i, 2 ) ) ) == As Name( "New Window" ),
Insert Into( windows, Char( Arg( arg i, 1 ) ) )
);
If( Head Name( arg i ) == "Assign" & Head Name( Arg( arg i, 2 ) ) == "Function",
Remove From( script, i );
Insert Into( script,
Substitute( Expr(
Assign( _arg1_, Function( _args_,
{Default Local},
_script_
) )
),
Expr( _arg1_ ), Arg( arg i, 1 )
,
Expr( _args_ ), Arg( Arg( arg i, 2 ), 1 )
,
Expr( _script_ ), If( Head Name( Arg( Arg( arg i, 2 ), N Arg( Arg( arg i, 2 ) ) ) ) == "Glue",
Insert( Arg( Arg( arg i, 2 ), N Arg( Arg( arg i, 2 ) ) ),
Eval Expr( self = Namespace( Expr( self << Get Name ) ) ),
1
)
,
Eval Expr(
Glue(
self = Namespace( Expr( self << Get Name ) ),
Expr( Arg( Arg( arg i, 2 ), N Arg( Arg( arg i, 2 ) ) ) )
)
)
)
)
,
i
)
)
);
Insert Into( script, 0 );
Eval( script );
For( w = 1, w <= N Items( windows ), w++,
win = Eval( Parse( windows[w] ) );
::modify display tree functions( self, win );
Eval( Eval Expr(
win << On Close(
Local( {self = Namespace( Expr( self << Get Name ) )},
Try( self:on close );
Delete Namespaces( Force( 1 ), self )
)
)
) )
);
self
);
script = {
a = 1;
__tables = {};
add table = Function( {_table},
Insert Into( self:__tables, _table )
);
close tables = Function( {},
For( i = 1, i <= N Items( self:__tables ), i++,
Try( Close( self:__tables[i], No Save ) )
)
);
func = Function( {b},
Show( b + self:a )
);
on close = Function( {},
Print( "Closing!!" );
self:close tables;
);
run button = Function( {},
Print( "You pressed the button" );
table = Open( "$SAMPLE_DATA/Big Class.jmp" );
self:add table( table << Subset( All Rows, All Columns, Not Linked ) );
Close( table, No Save );
);
win = New Window( "teest",
List Box( {"A","B"}, <<SET function=""></SET>두 개의 전역 함수를 이미 로드했다면 스크립트에서 제외할 수 있습니다. 이 함수는 이름 공간 내의 함수를 수정하여 자신이 있는 네임스페이스를 인식하고 수정하는 역할을 합니다. <<설정 기능( ... ) 표시 트리의 메서드를 사용하여 범위 지정 네임스페이스 내에서 관련 함수를 호출합니다.또한 자동으로 설정됩니다. <<닫을 때() 윈도우 실행 방법 self:on close() 기능(있는 경우).
기본적으로 범위 지정이 삭제됩니다. 본인 창이 닫힐 때의 네임스페이스.이것이 항상 원하는 동작은 아니지만 이 간단한 데모에서는 충분합니다.
스크립트의 마지막 두 줄은 각각 창을 열지만 그 사이에 혼선이 없습니다(버튼을 눌러 일부 테이블을 로드할 수 있으며 창이 닫히면 테이블도 자동으로 닫힙니다)
안녕하세요 @miguello ,
당신이 지적했듯이 변수 ns는 네임스페이스뿐만 아니라 각 스크립트에 고유해야 합니다. @jthi는 Names Default to here(1)를 사용하여 이 문제를 해결합니다. 이것을 명시적으로 정의하고 작동 방식을 더 잘 이해하려면 몇 개의 다른 창에서 다음 두 줄을 실행해 보세요.
here:ns = New Namespace();
here:ns:a = random normal();
그리고 사용하다
show namespaces()
각 네임스페이스에서 a의 값을 보려면 호출
here:ns:a
각 개별 창에서 해당 창의 값을 반환합니다. 다른 창에서 다음을 실행합니다.
Names default to here(1);
ns = New Namespace();
ns:a = random normal();
그리고 이것이 이전 예제와 같은 방식으로 동작하는 것을 주목하세요. here 네임스페이스 없이 시도하면 a에 대한 모든 참조가 같은 값을 반환하여 동일한 네임스페이스에서 온 것임을 나타냅니다.
그래서 그냥 넣어요
Names default to here(1);
스크립트 맨 위에 를 추가하면 문제가 해결 될 수 있습니다 . 또한 모든 변수를 여기 네임스페이스에 바로 넣어서 새로운 명명된 네임스페이스를 만드는 것을 완전히 피할 수도 있습니다.
인스턴스라고 하셨는데, 여러 개의 include를 한다는 뜻인가요? 아니면 함수처럼요?
Names default to here(1);
create_instance = function({ns},
Eval(EvalExpr(
nw = new window("Test",
window:ns = namespace(Expr(ns << Get name()));
<< On Close(
Delete Namespaces(force(1), window:ns);
),
Buttonbox("Press Me",
print(window:ns << Get name());
show(window:ns:x, window:ns:y);
)
)
));
);
create_instance(ns1 = new namespace({x=14;y=28}));
create_instance(ns2 = new namespace({x=140;y=280}));
제게는 이게 맞는 것 같아요.
*수정* 사실 더 쉬워요. eval expr은 런타임에 필요한 게 아니니까 필요도 없어요.
create_instance = function({ns},
nw = new window("Test",
window:ns = ns;
<< On Close(
Delete Namespaces(force(1), window:ns);
),
Buttonbox("Press Me",
print(window:ns << Get name());
show(window:ns:x, window:ns:y);
)
)
);
create_instance(ns1 = new namespace({x=14;y=28}));
create_instance(ns2 = new namespace({x=140;y=280}));