:- 演算子
使い方
m:-e
:-e
|
説明
|
|
•
|
バイナリーメンバーの選択演算子 :- は、 モジュールでエクスポートされた関数名に対し外部から直接スコープするために利用します。この演算子は、非可換で、左結合演算子です。 第 1 (左) オペランドは評価され、モジュール名です。第 2 (右) オペランドは、評価されず、最初のオペランドとして評価するモジュールからエクスポートされた記号でなければなりません。
|
|
重要: :- 演算子の第2オペランドが記号以外のものになると構文エラーとなります。:- 演算子の第 1 オペランドが、モジュール以外を評価すると実行時エラーとなります。
|
•
|
:- 演算子は、また、その単一のオペランドが記号であるような プリフィックス演算子として使用することもできます。 スコープ内に sym に対するローカルの束縛があっても、:-sym という表現は、sym のグローバルインスタンスを評価します。
|
•
|
:- 演算子の第 2 オぺランドが評価されないということは、実行時に与えられる出力名を使用して動的にメンバー選択表現を構成したい場合、問題となります。このため、インデックスを付ける操作 ([]) は、つぎのような方法でオーバーロードされてきました。モジュール m に対して、式 m[e] は、結果として f になる式 e を最初に評価した後、メンバー選択表現 m:-f に対して評価します。
|
•
|
m[e] の部分式 e は評価されるため、e を名前としてこの構文を使用するモジュールメンバーにアクセスする場合、未評価とするための (右) 引用符を使用する必要がしばしばあります。 さらに、 同じ外部表現をもつローカル名がスコープ内にある場合、:- 演算子を単項の前に置く形式として使用しなければなりません (インデックス は、グローバル名であることが仮定されているものとします)。たとえば、numtheory パッケージの出力される手続き orderを 呼び出すためには、numtheory[ ':-order' ] を使用してください。 (numtheory パッケージは、モジュールとして 実現されているため、等価なものとして numtheory:-order を使用することができますが、後者の構文は、モジュールに基づくパッケージに関してのみ動作します。)
|
|
|
例
|
|
>
|
m := module() export e; e := 2 end:
m:-e;
|
| (2.1) |
>
|
m:-3; # a syntax error, since 3 is not a symbol
|
on line 64, syntax error, unexpected number:
m:-3; # a syntax error, since 3 is not a symbol
^
m:-f; # another error, since m does not export the symbol `f'
Error, module does not export `f`
| |
>
|
StringTools:-Reverse( "abc" );
|
| (2.2) |
>
|
S := SimpleStack( a, b, c ):
S:-pop(); S:-pop(); S:-pop();
|
Warning, the protected name order has been redefined and
unprotected
| |
>
|
order( series( exp( s ), s ) );
|
Error, invalid input: numtheory:-order expects its 1st
argument, n, to be of type integer, but received
series(1+1*s+1/2*s^2+1/6*s^3+1/24*s^4+1/120*s^5+O(s^6),s,6)
| |
>
|
:-order( series( exp( s ), s ) );
|
| (2.4) |
>
|
r := Record( 'a' = 2, 'b' = 3, 'c' = 4 ):
r:-a, r:-b, r:-c;
|
| (2.5) |
>
|
slots := seq( r[ e ], e = [ a, b, c ] );
|
| (2.6) |
予め定義された大域的(グローバル)な記号を使用したり、表す出力をかくための :- のプリフィックス形式。 QUAT および `+` の両方についての使用に注意してください。
>
|
Q := module()
export `+`;
`+` := proc( a, b )
local answer;
if andmap(type,[a,b],'specfunc( algebraic, :-QUAT )' )
and map( nops, [ a, b ] ) = [ 4, 4 ] then
answer := ':-QUAT'( seq( op( i, a ) + op( i, b ), i = 1 .. 4 ) );
if andmap( Testzero, [op]( 2 .. 4, answer ) ) then
op( 1, answer )
else
answer
end if
elif type(a,'specfunc( algebraic, :-QUAT )' ) then
procname( a, ':-QUAT'( b, 0, 0, 0 ) )
elif type(b,'specfunc( algebraic, :-QUAT )' ) then
procname( ':-QUAT'( a, 0, 0, 0 ), b )
else
# Call the global `+`
:-`+`( a, b )
end if;
end proc;
end module:
use Q in
'QUAT'( 1, 2, 3, 4 ) + 'QUAT'( 1, -2, -3, -4 ) + x;
'QUAT'( 1, 2, 3, 4 ) + 'QUAT'( -1, 2, 4, 3 - y ) + x;
2 * x + y
end use;
|
これらの例は、パッケージの出力にアクセスする際、未評価とするための引用符 と :- 演算子をプリフィックス形式を使用する必要があることを説明します。 引用符は、常に必要です。なぜなら、最上位レベルで割り当てられるものについて制御することができないためです。 :- プリフィックス演算子は、衝突 を与えるローカルな名前がある場合に限り使う必要があります。
>
|
midpoint := 2:
p1 := proc(a, b)
local midpoint;
midpoint := 3;
2 * student[ ':-midpoint' ]( a, b ) / midpoint
end proc:
p2 := proc(a, b)
local midpoint;
midpoint := 3;
2 * student[ 'midpoint' ]( a, b ) / midpoint
end proc:
p3 := proc(a, b)
local midpoint;
midpoint := 3;
2 * student[ :-midpoint ]( a, b ) / midpoint
end proc:
p1( [1,2],[3,4] ); p2( [1,2],[3,4] ); p3( [1,2],[3,4] );
|
これら 3 つのルーチンでは、p1 のみが正しく動作します。
|
|