JSL ヘルプ: Set Function() コマンド構文のヘルプこんにちは、みんな、
別の JSL プログラミングの質問に戻ります。 それは他の投稿に関連しています。たとえば、ここ。
チェックボックスがチェックされている(状態= 1)場合、選択された行(RSquareが負である行である可能性があります)が選択されて非表示になり、削除されるため、更新されたグラフビルダーが機能するCheck Box()機能が必要です。は、目的の出力を示しています。 次に、ボックスがオフになっている場合 (state=0)、これらの行の非表示と除外が解除されます。 私が使用している Set Function() 呼び出しは以下のとおりです。 Set Function() の「スクリプト」を手動で実行すると機能しますが、自動的には実行されません。 自動的に更新するには何が足りないのかわかりません。 素敵な投稿を見つけましたここ、そして私はやろうとしています何かこの人がやったことと似ていますが、グラフビルダーの更新が目的です。
JSL Set 関数呼び出し:
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>
出力の開始時、またはチェックボックスが state = 0 のとき。:

チェックボックスが state = 1 の場合に必要な出力:

データ テーブルを右側のレポートとして更新して、除外された行が右側のレポート ビューから削除されるようにすることもできればよいのですが、これは思っているよりもはるかに難しいと思います。 Set Function() コマンドに Get As Report 更新を追加しようとしましたが、何も起こりません。
フィードバックは大歓迎です、ありがとう!、
DS
データのブレンディングとクリーンアップRe: JSL ヘルプ: Set Function() コマンド構文のヘルプ日々の仕事では、むしろ逆の問題に直面しています。
不可: 同じ名前空間を共有する 2 つのウィンドウ
ただし: 2 つのスクリプトは *) 共通点を共有することがあります。ここネームスペース。
ある JSL ファイルを別の JSL ファイルにインクルードすると、実行時、含まれているスクリプトは、ここメインの jsl ファイルの名前空間。
しかし、コードのいくつかの行をデバッグし、2番目のスクリプトから実行したい場合、含まれているものをどのように指定すればよいですかスクリプト_Bへのアクセスここメインスクリプトの名前空間? 2 秒前、script_B のコードを実行したとき、その名前空間にアクセスできました。
https://community.jmp.com/t5/Discussions/Debugging-Jmp-applications/mp/701121/highlight/true#M88566
Re: JSL ヘルプ: Set Function() コマンド構文のヘルプ感謝、 @Erratic Attack Jmp でのスコープ設定の仕組みについては、美しい例をご覧ください。
理解に近づくのにとても役立ちました...
今までは何が何だか理解できなかったのですが、 @drewfogliaという意味

で効率と再現性を高めるための基本的なスクリプト作成: より少ない作業でより多くの作業を行う (2019-US-TUT-290)
あなたの例は、これが真実ではないことをうまく示しています。
ここでの私たちの経験がドリューの声明と異なるのはなぜですか?
これは、ウィンドウが同じ JSL エディター ウィンドウから作成されているためだと思います。
最初の TEST ウィンドウを開いた後も、スクリプト ウィンドウが参照されたオブジェクトに引き続きアクセスできることは非常に役立ちます。テブそしてTB 。
2番目のTESTウィンドウを開いた後、テブそしてTB 2 番目のウィンドウのオブジェクトを参照します。これにより、明らかに最初のウィンドウの機能が損なわれます (入力されたテキストはTB 、つまり 2 番目のウィンドウ)。
さて、boh の主張をリンクすると、両方の Windows が共通の JSL エディターを共有していない場合はどうなるでしょうか。
-> Drew が講演で発表したように、どちらも独立した NameSpace を持つことになります。
そのためのオプション:
a) スクリプトを閉じて再度開き、2 番目のウィンドウを作成します。
b) メニューからスクリプトを呼び出します。

Re: JSL ヘルプ: Set Function() コマンド構文のヘルプこんにちは@Erratic Attack 、
ご返信と詳細な投稿をありがとうございます。 私はプロのプログラマーではないので、これを解決するには確かに時間がかかります。これの多くは私にとってまだ新しいものです。
ありがとう!、
DS
Re: JSL ヘルプ: Set Function() コマンド構文のヘルプ@ih 、JMP が予想どおりにスコープを実行しない例 (特に Python などからのもの) として、このスクリプトから 2 つのウィンドウを起動するだけです。名前は 2 番目のウィンドウにのみリンクされ、最初のウィンドウにはリンクされません。これは、私が発見したスコープ設定に関して人々が抱えている最大の問題です (ただし、唯一の問題ではありません)。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>
このスクリプトには 2 つの対話型 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()` として定義し、上記のように各関数に self 定義を注入します (もちろん、「#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 つであるか、2 番目の引数が {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>このスクリプトには多くの定型文が含まれていますが、より明示的にスコープを制御したい場合に必要です。特に、「一度に 1 つのウィンドウだけを開いてください!」とユーザーに指示したくない場合に使用します。メタプログラミングのステップを作成するのは少し面倒で、確かに多くの学習が必要ですが、一度理解すれば、とてもやりがいがあり、より簡潔で保守しやすいコードも可能になります。
ここで私がまったく示してきたのは、非常にうまく機能し、インタラクティブな UI 生成を簡単にできるクラス (JMP14+ NewObject クラスとは完全に別) を作成する機能です。
これは大変な作業であることはわかっていますが (UI スクリプトを構築するための最初のアプローチからはかけ離れた、より重要な点です)、複数の小さな UI スクリプトを作成している場合、メタプログラミングの作成に時間がかかることになります。ラッパー (一度だけ行う必要があります) はすぐに価値があります。
Re: JSL ヘルプ: Set Function() コマンド構文のヘルプこんにちは@Erratic Attack 、
ご意見ありがとうございます。 あなたが私に Namespace() を勧めたのはこれが 2 回目であることに気付きました ;-)。
その結果、私は過去 1 日半をかけて、スクリプト ガイドで NameSpace の使用法を読んできました。このガイドは、Scripting Index よりも優れていますが、実際にどのように使用しているのかなど、最良の例はまだ提供されていません。使用状況に応じてネームスペースを使用する方法について、JMP 14 スクリプト ガイドまたはスクリプト インデックスよりも優れた入門書はありますか?
正直、私はあなたがやっていることを完全に理解できていないので、もっとよく学ぶ必要があります。 ただし、ここでの投稿と、他の投稿で提供したサンプルコードに基づいて、ここ, Namespace() を使用して最初のウィンドウを呼び出すスクリプトのセクションを書き直すことができました。 しかし、私のそれほど優れたスクリプトスキルではなくても、後続のウィンドウや表示をどのようにスクリプトで記述すればよいのか、まだよくわかりません。 プログラムによる方法に切り替える前に、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() コマンド構文のヘルプこんにちは@Erratic Attack 、
私の経験から言えば、変数のスコープは一貫しています。 それは直感的ではないかもしれませんが、私は常に予測可能であると感じてきました。不一致が発生した場合は、スクリプト ガイドを詳しく調べて、さまざまなシンボルのスコープがどのように設定されているかをクロスチェックしてみるとよいでしょう。
状況によっては、通常は探索的分析や対話的に実行されるスクリプトの場合、呼び出しコンテキスト関数を使用して関数呼び出しを簡素化することで大きな成功を収めてきました。 たとえば、ログ関数はファイルまたはウィンドウにメッセージを送信し、毎回入力/コピー/ペーストすることなく、イテレータまたはステップ値を含めることができます。
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()
);
)
);