Re:変数が式でどのようにスコープされているかを理解するのに助けが必要ですスコープは次のようになります-で検索ローカル()存在する場合は名前空間、存在しない場合はルックアップここ()存在する場合は名前空間、存在しない場合はルックアップグローバル()名前空間。(また、現在のデータテーブルの列名も時々チェックします)。
最初のスクリプトで行っているのは、名前を付けることです"x" nにここ()値を持つ名前空間"変数" 、次に名前を入れます"exprA" nにここ()値を持つ名前空間Write( "ここに変数があります:" || x) 、次に名前を入れます"exprB" nにここ()値を持つ名前空間Glue(dt1 = Open( "$ SAMPLE_DATA / Big Class.jmp")、dt1 << On Close(exprA)) 。
最後にあなたは評価します"exprB" n --JMPは、最初にチェックしてこの名前を解決しようとします。ローカル()名前空間(存在しません)、次にここ()名前空間とそれを見つける-それでそれはに保存された式を実行しますスコープとして( "here"、 "exprB") 。
次に、テーブルをロードして配置しますexprAウィンドウを閉じるスクリプトとして。
これでスクリプトが終了するので、ここ()スクリプト用に作成された名前空間が削除され、メモリがクリアされます。
テーブルを閉じると、文字が見つかりますexprA終了スクリプトとして、上記のように名前のスコープを設定しようとします(ローカル() 、ここ() 、グローバル() )、今回のみありませんここ()名前空間であり、3つの名前空間のいずれにも名前が見つからないため、エラーがスローされます。
一般に、別のスコープで実行される式に静的な値として変数を追加する場合は、次のいずれかを使用します。 Eval(Eval Expr(...; Expr(Name Expr(val)); ...))または他の同等のもの。
私の個人的な経験では、スクリプトごとに明示的な名前空間(匿名)を作成してから、すべての変数をそれぞれの名前空間に手動でスコープします。その後、必要に応じてこの名前空間を渡すことができます(もちろん、スクリプトが完了したとき/ウィンドウが閉じたときに名前空間をクリアして閉じます)。
スクリプトを機能させる方法の例を次に示します。
Names Default To Here( 1 );
x = "Variable";
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose( Write( "\!NHere is variable: " || Expr( x ) ) );
) );
また
Names Default To Here( 1 );
x = "Variable";
exprA = Expr(
Write( "\!NHere is variable: " || x )
);
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose( x = "rather"; Expr( Name Expr( exprA ) ) );
) );
また
Names Default To Here( 1 );
self = New Namespace();
self:x = "Variable";
self:exprA = Expr(
Write( "\!NHere is variable: " || self:x )
);
Eval( Eval Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt1 << OnClose(
Local( {self = Namespace( Expr( self << Get Name ) )},
self:exprA;
Delete Namespaces( Force( 1 ), self )
)
);
) );多くのプログラミング言語はローカル名前空間を作成し、それらが不要になるまで参照カウンターを使用して維持しますが(Pythonと関数など)、JSLは実際にはそれを行わず、それを維持するのはコーダー次第です。永続性とスコープが必要です。 内部のコード<<クローズ時(...)メッセージは、名前やスコープを管理せずに、メッセージを作成したスクリプトとは完全に別のコンテキストで評価されます。
これがお役に立てば幸いです。少し混乱する可能性があります。
Re: 変数が式でどのようにスコープされるかを理解するのに助けが必要ですジョーダン、どうもありがとう、それは動作を説明しています。 実際のスクリプトには、OnClose ステートメントで変数を共有する多くのテーブルがあるため、名前空間を使用した提案された方法が気に入っています。
次のコードを理解するのを手伝ってくれませんか:
Local( {self = Namespace( Expr( self << Get Name ) )},
self:exprA;
Delete Namespaces( Force( 1 ), self )
)Local は名前をローカル変数に解決しますが、それはどういう意味ですか? 中括弧でいくつかの変数を定義する必要があるのはなぜですか?その目的は何ですか? (スクリプトの索引とドキュメントの両方で、これについてはあまり説明されていません)。
Re: 変数が式でどのようにスコープされるかを理解するのに助けが必要です短い答え - 名前が外部のものを上書きしないようにします地元()ブロック。
長い答え:
私の関数では、次のように書きます。
some function = Function( {arg1, arg2, etc},
{Default Local},
self:arg1 = arg1;
self:arg2 = arg2;
//do something amazing!
//call a method:
self:call method
);
call method = Function( {},
//do something else amazing!
1
)
次に、メタプログラミングを使用して定義します自己各関数に参照を挿入すると、次のように変換されます。
self:some function = Function( {arg1, arg2, etc},
{Default Local},
self = Namespace( "#48" );
self:arg1 = arg1;
self:arg2 = arg2;
//do something amazing!
//call a method:
self:call method
);
self:call method = Function( {},
{self},
self = Namespace( "#48" );
//do something else amazing!
1
)これにより、Python クラスと非常によく似たものが作成されます (私のコードは上記のステートメントとは大きく異なりますが、概念的には似ています)。私が絶対に起こらないようにしたいことは、参照を持っていることです自己他の値で上書きされます。
関数で私が持っていると想像してください待つ( 1 )何らかの理由で機能し、その待機フェーズ中に、再定義するスクリプトが添付されたテーブルを誰かが閉じます自己-- 待機ステートメントが完了すると、自己現在、別の変数を参照しており、混乱が続いています。
の地元()関数はローカル ブロックを作成し、最初の引数 (リスト) で定義された変数はそのブロックに対してローカルです。
Names Default to Here( 1 );
a = 1;
b = 4;
Print( "Before Local Block:" );
Show( a, b );
Local(
{local_var1, local_var2, b},
local_var1 = 4;
local_var2 = 2;
b = 9;
Print( "Inside Local Block:" );
Show( local_var1, local_var2, a, b );
a = 5;
);
Print( "After Local Block:" );
Show( Try( local_var1, Empty() ), Try( local_var2, Empty() ), a, b )
/*:
"Before Local Block:"
a = 1;
b = 4;
"Inside Local Block:"
local_var1 = 4;
local_var2 = 2;
a = 1;
b = 9;
"After Local Block:"
Try(local_var1, Empty()) = Empty();
Try(local_var2, Empty()) = Empty();
a = 5;
b = 4;ここで両方を再定義しますaとbローカルブロック内ですが、 bローカルブロックの外側は影響を受けませんaは。パッティング自己ローカル変数として使用するのが最も安全な方法です。
変数が式内でどのようにスコープされるかを理解するのに助けが必要ですこんにちは皆さん、
簡単なサンプルスクリプトがあります。 ここでの変数のスコープは何なのか、また、ある方法では機能し、別の方法では機能しない理由を誰かが説明してもらえますか?
最初のスクリプトは次のとおりです。
Names default to here(1);
Clear Globals();
x="Variable";
exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;アイデアは、テーブルを開いて、テーブルが閉じられたときに実行する必要がある式をそれに与えることです。 Expression は、スクリプトのいくつかの変数を評価して変更します (この例ではありません)。
書かれている方法では機能しません - 何も起こりませんが、実際のスクリプトでは参照が見つからないというだけです。
さて、ExprA をグローバルにしてみましょう。
Names default to here(1);
Clear Globals();
x="Variable";
::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;これで式は認識されますが、x 変数が認識されないため、まだ機能しません。
OK、x もグローバルにしましょう。
Names default to here(1);
Clear Globals();
::x="Variable";
::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 << OnClose(exprA));
exprB;これで動作します:
Scriptable[]Here is variable: Variable
// Close Data Table: Big Class
Close( "Big Class" );
質問: なぜこのように機能し、最初の方法では機能しないのでしょうか? 私から見ると、それはうまくいくはずでした。
このスクリプトでグローバル変数を使用するのは好きではありません。それを機能させる他の方法はありますか?
高度な統計モデリング自動化とスクリプト作成消費者および市場調査データアクセスデータのブレンディングとクリーンアップ実験計画法マスカスタマイゼーション品質およびプロセスエンジニアリング