式とは、評価可能な演算子によってつながれた変数、定数、および関数の任意の組み合わせです。「JSLの構成要素」章の「名前解決のルール」(94ページ)の節では、JMPがどのように式を評価するかについて説明しています。ここでは、いつJMPが式を評価するかについて学習します。JMPはステートメントを順番に評価します。式を使用して、式を割り当て、必要に応じてその式を修正または実行することができます。
いつ式を評価するかを制御する演算子は、ExprとEvalです。これらは、評価を遅延させる演算子と評価を促す演算子とみなすことができます。Exprは、引数を評価するのではなく、式としてそのままコピーします。Evalはその反対の処理をします。つまり、引数の値を求めてから、その結果を使って式全体を評価します。
ExprとEvalは、JMPに対していつ式として認識し、いつ式の評価結果を戻すかを指示する、クォート演算子と非クォート演算子とみなすことができます。
x = 1; y = 20;
Exprを使ってx+yを式として囲み、この式をaに割り当てた場合、aが評価されるときは、xとyの現在の値を使って式を計算し、結果を戻します。(例外として、Show、Write、およびPrintのユーティリティがあります。これらは、引数として名前だけを指定した場合、その名前に割り当てられている式を評価しません。)
x = 1; y = 20;
a = Expr( x + y );
a;
x = 1; y = 20;
Show( Name Expr( a ) );
x = 1; y = 20;
a = Expr( Expr( x + y ) );
Show( a );
式の値を求めるときは、Evalを使ってすべての層の式を評価します。
x = 1; y = 20;
Show( Eval( a ) );
x = 1; y = 20;
a = Expr( Expr( Expr( Expr( x + y ) ) ) );
b = a;
c = Eval( a );
d = Eval( Eval( a ) );
e = Eval( Eval( Eval( a ) ) );
式の扱いの詳細については、Morgan (2010)を参照してください。
JSL Quote()関数は、式の内容を、引用符で囲んだ文字列として戻します。文字列内のコメントと空白はそのまま維持されます。ログウィンドウでも構文の色分けが適用されます。
x = JSL Quote( /* クォートの開始 */
For (i = 1, i <= 5, i++,
// iの値を出力
Print( i );
);
// 式の終わり
);
Show( x );
出力では、JSL Quote()関数の内容が引用符で囲まれます。
x = " /* クォートの開始 */
// iの値を出力
// 式の終わり
Expr()関数の一般的な使い方は、スクリプトをグローバル変数に格納することです。これをマクロのようなものと考えることもできます。次のスクリプトを見てみましょう。
dist = Expr( Distribution( Column( :Name("身長(インチ)") ) ) );
dist;
For( i = 0, i < 3, i = i + 1, dist );
式の評価を明示的に指定するには、Eval()を使用してください。
Eval( dist );
ただし、列計算式における列に対しては、eval()は思い通りに動作しないことに注意してください。たとえば、
Formula( Log( Eval( Column Name( i ) ) ) );
Formula( Eval( Substitute( Expr( Log( xxx ) ), Expr( xxx ), Column Name( i ) ) ) );
Formula( Eval( Column Name( i ) ) + 10 );
Formula(Eval(Substitute(Expr(xxx+10), Expr(xxx), column name(i))))
グローバル変数を評価(実際にプラットフォームを起動)するのではなく、グローバル変数に保存されている式(上の例のdistに格納されている式Distribution(Column(:Name("身長(インチ)")))など)が必要な場合は、どうするのでしょうか。そのときは、Name Expr関数を使います。Name Exprは引数を評価しないで式として取り出します。ただし、引数がひとつの変数名だけの場合は、その変数に保存された式を、評価されていない状態で取り出します。
Exprが引数そのものを戻すのに対して、Name Exprは引数に保存されている式を検索します。Name Exprは式を得るために一番上の層だけを「開封」するのであり、すべての階層を開封するのではありません。
popVar = Expr( Summation( i = 1, N Row(), (y[i] - Col Mean( y )) ^ 2 / N Row() ) );
unbiasedPopVar = Substitute( Name Expr( popVar ), Expr( Wild()/N Row() ), Expr( (y[i] - Col Mean( y )) ^ 2 / ( N Row() - 1 ) ) );
a = 1; b = 2; c = 3;
x = Expr( a + b + c );
x; |
|
Eval( x );
|
単にxを呼び出しているのと同じ。
|
NameExpr( x );
|
|
Expr( x );
|
JSLには式にアクセスして式全体を調べる関数も用意されており、これらの関数はすべて、引数として名前または文字式のどちらかをとります。以下の例では、expressionArgは、変数の名前、または、変数と演算子などから構成される複合式のいずれかです。
expressionArgは、式を含む変数の名前、評価結果が式になるような式、またはExpr()で囲まれた式のいずれかです。
NArg (name)は、nameから式(評価されていない状態)を取り出し、引数の数を戻します。
NArg (Expr(expression))は、式expressionの引数の数を戻します。
たとえば、aExpr = {a+b,c,d,e+f+g};の場合
•
|
•
|
NArg(Expr({1,2,3,4}))は4となります。
|
expressionArgは、式を含む変数の名前、評価結果が式になるような式、またはExpr()で囲まれた式のいずれかです。
たとえば、aExpr = expr(a+b);の場合
•
|
r = Head(aExpr)はAdd()
|
•
|
r = Head (Expr(sqrt(r)))はSqrt()
|
•
|
r = Head({1,2,3})は{}となります。
|
expressionArgは、式を含む変数の名前、評価結果が式になるような式、またはExpr()で囲まれた式のいずれかです。
•
|
•
|
•
|
別の例としてaExpr = Expr(12+13*sqrt(14-15));の場合を示します。
•
|
Arg(aExpr,1)は12
|
•
|
Arg(aExpr,2)は13*sqrt(14-15)
|
•
|
Arg(Expr(12+13*sqrt(14-15)),2)は13*sqrt(14-15)
|
•
|
Arg(Arg(aExpr,2),1)は、aExprの第2引数の中の最初の引数、つまり13を戻します。
|
•
|
Arg(Arg(aExpr,2),2)はSqrt( 14 - 15 )
|
•
|
Arg(Arg(Arg(aExpr,2),2),1)は14 - 15
|
•
|
Arg(Arg(Arg(aExpr,2),2),3)はEmpty()
|
1.
|
内側のArgステートメントが評価されます。
|
Arg(aExpr,2)
Arg(Arg(aExpr,2),2)
// これはArg(Expr(13 * Sqrt( 14 - 15 ) ), 2)と等価
Arg(Arg(Arg(aExpr,2),2),3)
// これはArg (Expr(Sqrt( 14 - 15 ) ), 3)と等価
Arg(Arg(Arg(Arg(aExpr,2),2),1),2);
expressionArgは、式を含む変数の名前、評価結果が式になるような式、またはExpr()で囲まれた式のいずれかです。
たとえば、aExpr = expr(a+b);の場合
•
|
r = HeadName (aExpr)は"Add"
|
•
|
r = HeadName (Expr(sqrt(r)))は"Sqrt"
|
•
|
r = HeadName ({1,2,3})は"List"となります。
|
JMPのこれまでのバージョンでは、Arg、Narg、Head、およびHeadNameがそれぞれArgExpr、NArgExpr、HeadExpr、およびHeadNameExprとして実装されていました。基本的に働きは同じでしたが、引数の評価を行わない点が異なります。旧バージョンの形式は、今後のマニュアルには記載されなくなる予定です。
Eval Insertでは、文字列の中に含まれる式を評価することによって、文字列の部分置換を行えます。
Eval Insertでは、式の前後の文字を指定すると、その間の式が評価、展開されます。
resultString = EvalInsert(式が埋め込まれた文字列,開始区切り文字,終了区切り文字)
EvalInsertInto(式が埋め込まれた文字列を持つ変数,開始区切り文字,終了区切り文字)
区切り文字の指定はオプションです。デフォルトの開始文字は"^"、 デフォルトの終了文字は、開始文字と同じ文字です。
xstring = "def";
r = Eval Insert( "abc^xstring^ghi" ); // 戻り値が"abcdefghi";になる
r = "abc^xstring^ghi"; // 値を置き換え
Eval Insert Into( r ); // rが"abcdefghi";になる
// 区切り文字の指定
r = Eval Insert( "abc%xstring%ghi","%" ); // 戻り値が"abcdefghi";になる
// 開始値と終了値が異なる例
r = Eval Insert( "abc[xstring]ghi","[","]" ); // 戻り値が"abcdefghi";になる
数値にロケール固有の表示形式が含まれている場合は、<<Use Locale(1)オプションを含めます。次の例は、小数点の代わりにカンマを使用するロケール環境で実行したものです。
Eval Insert( "^1.2^", <<Use Locale( 1 ) );
Eval Listは、リスト内の式を評価し、その結果をリストにして戻します。
x = { 1 + 2, 3 + 4 };
y = Eval List( x ); // yは{3,7}になる
Eval Expr()は、内側の式だけを評価し、その結果を含む式を戻します。これと比較して、Evalは内側の式を評価し、結果を用いて式をさらに評価します。
x = Expr( Distribution( Column( Expr("X"||Char( i ) ) ) ) );
i = 3;
y = Eval Expr( x ); // Distribution( Column( "X3" ) )を戻す
// 2つのステップを取る方法
x = Expr( Distribution( Column( Expr( "X" || Char( i ) ) ) ) );
i = 3;
y = Eval Expr( x );
y;
// 1つのステップで済む方法
x = Expr( Distribution( Column( Expr( "X" || Char( i ) ) ) ) );
i = 3;
Eval( Eval Expr( x ) );
構文解析とは、プログラム言語の式として文字列を取り込むことです。JSLの式を文字列として保持しており、その文字列から式を構築したいとします。Parse関数は式を戻します。その式を評価するにはEval関数を使います。
x = Parse( "a=1" ) ; // 現在xには式a=1が入っている
Eval( Parse( "a=1" ) ); // 現在aには値1が入っている
y = Char( Expr( a = 1 ) ); // yは「a=1」という文字値になる
z = Char( 42 ); // "42"になる
Char( 42, 5, 2 ); // 文字値は"42,00"になる
数値にロケール固有の形式を維持するには、次の例のように、<<Use Locale(1)オプションを含めます。
Char( 42, 5, 2, <<Use Locale(1) ); // フランスのロケールで実行した場合、"42,00"になる
Parse( y );
Num( z );
Char(Expr(expression))
Char(name)
|
expression(式)を文字列に変換する。式はExprで囲む必要があります。囲まない場合、その評価結果が文字列に変換されます。
|
|
number(数値)を文字値に変換する。widthとdecimalは、形式を指定するためのオプションの引数です。デフォルトでは、width(フィールド幅)は18で、decimal(小数桁数)は99です。
|
||
Eval(x)
|
xを評価し、次いでxの結果を評価する(非クォート)。
|
|
xの中の式すべてを評価して、式を戻す。
|
||
Eval List(list)
|
リスト(list)内の式を評価した後のリストを戻す。
|
|
Expr(x)
|
||
xに格納されている式を評価せずに戻す。NameExprは、xが1つの変数名の場合、名前xを評価せずに戻すのではなく、その変数xに保存されている式を評価せずに戻します。その点を除けば、NameExprはExprと同じです。
|
||
Num("string")
|
||
Parse("string")
|
x = Expr( Distribution(Column( Expr("X"||Char( i ) ) ) ) );
i = 3;
x; // または
見つかりません。 'distribution'へのアクセスまたは評価 , 不正な引数( {"X" || Char( i )} ), distribution( Column( Expr( "X" || Char( i ) ) ) )
|
Eval(x)とxの呼び出しは同じ。
式distribution( column( expr( "X" || Char( i ) ) ) )を評価します。結果はエラーとなります。列名は、Expr()関数によって囲まれているため、"X"||Char(i)のように認識されます。
|
xに保存されている式Distribution(Column(Expr("X" || Char(i))))をそのまま戻す。
|
|
y; // または
一変量の分布[]
|
Eval(eval expr(x))とyの呼び出しは同じ。
Distribution(Column("X3"))を評価し、プラットフォームを起動します。
|
式全体を文字列としてクォートする。必要に応じて、¥!"というエスケープ文字を追加します。
|
|
一変量の分布[]
|
この例は、少なくともこれを2つのステップに分解する必要があることに注意してください。これを1つの大きなステップに組み合わせると、Eval Expr関数が、Parse層以下の内容を評価せずにそのまま残してしまうため、別の結果となります。
Eval( EvalExpr( Parse( Char( NameExpr(x))))); |