の終わりにクラス定義の使い方私は、JSL クラスのインスタンスがコピーするのが難しいという点で興味深い点があることをほのめかしました。 X がインスタンスを参照する場合、Y=X は Y と X の両方になります。参照に同じ実例。 インスタンスをユーザー定義関数に渡すときも同じことが起こります。関数の値は次のとおりです。いいえインスタンスのコピー。それ参照しますに同じ実例。 したがって、関数内のインスタンスを変更すると、呼び出し元のインスタンスも変更されます。 行列を関数に渡し、関数内で行列を変更したことがあり、呼び出し元のコピー更新されると、JSL は値によって引数をユーザー関数に渡します。
JMP passes arguments by making copies, but...JMP passes arguments by making copies, but...JMP passes arguments by making copies, but...JMP passes arguments by making copies, but...JMP は引数をコピーして渡しますが...
行列がコピーされるため、関数内の行列への変更はオリジナルではなくコピーに対して行われることに注意してください。 大きな黒い参照ドットもコピーされますが、それが参照するオブジェクトはコピーされないことに注意してください。 この図を見ていないため、初心者の JAVA プログラマーは多くの頭痛の種を引き起こします。 関数内では、変数に対して 2 つのまったく異なることを実行できます。ある。
- a:set(42); のようなメソッドを呼び出すことができます。
- a=42 のような値を割り当てることができます。
(1) を変更した場合アーガイルオブジェクトの値は 3 ~ 42 です。 おそらくこれがあなたがやりたいことです。 (2) の場合、次の大きな黒い点を上書きします。ある42で。 おそらくそんなつもりはなかったでしょう。
次のコードでは、他のオブジェクトへの参照を保持するオブジェクトを使用します。 すべてのオブジェクトには next() メソッドがあるため、オブジェクトを興味深い方法で構成できます。 next() メソッドは、一連の値の次の値を生成します。 一部のオブジェクトは定数を表し、常に同じ次の値を生成します。 その他、add オブジェクトなど、他のオブジェクトには 2 つのオブジェクト (+ 演算子の左側と右側) があります。 Add:next() は left:next() と right:next() を呼び出し、2 つの答えを加算します。
完全な JSL が添付されています。 こちらが写真を挟み込んだ状態です。 最も単純なクラスから始めましょう。
// number/matrix wrapper class
Define Class(
"vwrap",
m_v = .; // holds the number or matrix
_init_ = Method( {v},
If( Type( v ) == "Class",
Throw( "vwrap is for number or matrix, not class " || Char( v << getname ) )
);
m_v = v;
);
set = Method( {v},
If( Type( v ) == "Class",
Throw( "vwrap is for number or matrix, not class " || Char( v << getname ) )
);
m_v = v;
);
next = Method( {},
m_v; // return
);
);Vwrap はクラスの名前で、数値または行列の値をラップします。 これには、認識できない値を拒否するセッターと、シーケンス内の次の値を返す next() という名前のゲッターがあります。 NewObject(Vwrap(42)) と書くのはちょっと見苦しいので、Vwrap を作るためのヘルパー関数も作りましょう。
// helper function v(...) converts a scalar or matrix to a vwrap, or returns an instance unchanged
v = Function( {x},
If( Type( x ) == "Class",
If( !(x << Contains( "next" )),
Throw( "v expects number, matrix, or one of the classes it supports, not class " || (x << getname) )
);
x; // x supports a next function, it is probably OK
, // else
If( !Is Number( x ) & !Is Matrix( x ),
Throw( "v expects number or matrix, not " || Type( x ) )
);
New Object( vwrap( x ) ); // wrap the number or matrix
)
);v(...) は、クラス インスタンスを使用して、またはスカラーまたは行列を使用して何度も呼び出されます。クラス インスタンスを取得した場合は、クラス インスタンスを変更せずに返す必要があります。 混同される可能性のある他のクラスがある場合に備えて、クラス内に next() があるかどうかを同時にチェックすることもできます。
次に、グラフを作成する定型的な機能です。
// global function gr(...) makes a graph
gr = Function( {Xvar, Yvar, title, n},
{Xs, Ys, dt}, // locals
Yvar = v( Yvar );
Xvar = v( Xvar );
Ys = J( n, 1, Yvar:next() );
Xs = J( n, 1, Xvar:next() );
dt = As Table( Ys || Xs, <<INVISIBLE></INVISIBLE>X パラメータと Y パラメータに対する v() の呼び出しがわかります。これらは、ラップされる単純な数値、または next() メソッドを備えた他のクラスにすることができます。 次に、J() 関数が N 値の行列を作成し、非表示のテーブルが作成され、不要になった非表示のテーブルを閉じるちょっとした魔法を使ってグラフ ビルダーが実行されます。 試してみよう。
gr( 13, 42, "Value 13,42", 1 );
A single point, at x=13, y=42A single point, at x=13, y=42A single point, at x=13, y=42A single point, at x=13, y=42単一点、x=13、y=42
待ってください。改善されるでしょう...next() の連続呼び出しで 0、1、2、3、... を返すカウンター クラスを作成しましょう。
// counter class
Define Class(
"counter",
m_rate = .; // non zero increment
m_pos = empty(); // internal position
_init_ = Method( {rate},
m_rate = v( rate );
);
next = Method( {},
rate = m_rate:next();
// see peek() comment in "sin" class
If( Is Empty( m_pos ),
result = 0 * rate; // get scalar or matrix dimension on first call
m_pos = rate; // for next time
, // else
result = m_pos; // from last tim
m_pos += rate; // for next time
);
result; // return
);
);_init_ メソッドは、カウンターが増加する速度を決定するレートを受け取ります。 Rate は定数 (通常は 1) にすることも、別のクラス インスタンスにすることもできます。 これはカウンターを作成するためのヘルパー関数と最初のグラフです。
// global function to make a counter
ctr = Function( {rate = 1},
New Object( counter( rate ) )
);
gr( ctr(), ctr() , "count up A (equal steps)", 5 );X 軸と Y 軸の 2 つの別々のカウンター インスタンスが gr(...) に渡されたことに注目してください。
Two counters, running in parallel, for five steps starting at zero.Two counters, running in parallel, for five steps starting at zero.Two counters, running in parallel, for five steps starting at zero.Two counters, running in parallel, for five steps starting at zero.2 つのカウンターが並行して実行され、ゼロから始まる 5 つのステップが実行されます。
さて、別のこととして、カウンターのレートを別のカウンターにしてみましょう。
// this variation begins to show the power of composition
gr( ctr(), ctr( ctr() ), "count up B (first step is 0)", 5 );
The first step is zero because the rate counter's first result is zero.The first step is zero because the rate counter's first result is zero.The first step is zero because the rate counter's first result is zero.The first step is zero because the rate counter's first result is zero.レート カウンタの最初の結果が 0 であるため、最初のステップは 0 になります。
このグラフの Y 軸は、2 つのカウンターの機能構成を使用しています。 sin() クラスを追加しましょう。
// sin() wrapper class
Define Class(
"sin",
m_rate = .; // 0<STEP><PI. m_amp=".;"> Sin( m_pos += m_rate:next() ) // return
);
);</PI.></STEP>
Sin は、定数または他のクラス インスタンスによって決定される周波数と振幅で無限の正弦波を生成します。 内部位置も保持します。 コメントから、さらに検討が必要であることがわかりますが、このデモでは機能します。 これは単一サイクルの波形です。
gr( ctr(), New Object( Sin( 2 * Pi() / 100, 3 ) ), "sin()", 101 );
Single cycle of sine waveSingle cycle of sine waveSingle cycle of sine waveSingle cycle of sine wave正弦波の 1 周期
別のカウンターが増加するカウンターと同様に、正弦波は可変周波数を持つことができます。
gr( ctr(), New Object( Sin( New Object( Sin( .0002, 1 ) ), 3 ) ), "variable frequency", 1000 );
Ramping up the frequency using the first bit of another sine waveRamping up the frequency using the first bit of another sine waveRamping up the frequency using the first bit of another sine waveRamping up the frequency using the first bit of another sine wave別の正弦波の最初のビットを使用して周波数を上昇させる
また、2 つの異なる周波数の正弦波を相互にプロットすることができます。
gr( New Object( Sin( 4 * Pi() / 99, 3 ) ), New Object( Sin( 6 * Pi() / 99, 3 ) ), "2X3 sin()", 100 );
Simple integer ratios make nice patternsSimple integer ratios make nice patternsSimple integer ratios make nice patternsSimple integer ratios make nice patterns単純な整数比で素敵なパターンを作る
別のクラスとヘルパー関数。クラスは 1 つ以上の他のクラスを追加し、オフセット ヘルパーは定数...またはおそらく...未テストの別の関数を追加します。
// add class
Define Class(
"add",
m_a = {};
//m_b = .;
_init_ = Method( {a, b = Empty()},
If( Is Empty( b ),
For( i = 1, i <= N Items( a ), i += 1,
Insert Into( m_a, v( a[i] ) )
),
m_a[1] = v( a );
m_a[2] = v( b );
)
);
next = Method( {},
result = m_a[1]:next();
For( i = 2, i <= N Items( m_a ), i += 1,
result = result + m_a[i]:next()
);
result;
);
);
// helper function uses add to offset another value by off
offset = function({off,x},
newobject(add(off,x))
);オフセット ヘルパーを使用すると、初期ステップが 0 だった初期のグラフの 1 つを、初期ステップが 1 になるように再加工できます。
// compared to a previous example, this one increments earlier
gr( ctr(), ctr( offset(1,ctr( 1 )) ), "count up C (first step is 1)", 5 );
Now all the steps are one bigger than before.Now all the steps are one bigger than before.Now all the steps are one bigger than before.Now all the steps are one bigger than before.これで、すべてのステップが以前よりも 1 つ大きくなりました。
// building a square wave by summing odd harmonics
n = 100;
basefreq = 2 * Pi() / n;
freq1 = New Object( Sin( 1 * basefreq, 1 / 1 ) );
freq2 = New Object( Sin( 3 * basefreq, 1 / 3 ) );
freq3 = New Object( Sin( 5 * basefreq, 1 / 5 ) );
freq4 = New Object( Sin( 7 * basefreq, 1 / 7 ) );
sum = New Object( Add( {freq1, freq2, freq3, freq4} ) );
gr( ctr(), sum, "4 Odd Harmonics", n + 1 );
Summing odd harmonics at reduced amplitude approximates a square wave.Summing odd harmonics at reduced amplitude approximates a square wave.Summing odd harmonics at reduced amplitude approximates a square wave.Summing odd harmonics at reduced amplitude approximates a square wave.振幅を小さくして奇数高調波を合計すると、方形波に近似します。
// same square wave, a lot more odd harmonics
n = 200;
basefreq = 2 * Pi() / n;
freqs = {};
For( i = 1, i <= 23, i += 2,
Insert Into( freqs, New Object( Sin( i * basefreq, 1 / i ) ) )
);
gr( ctr(), New Object( Add( freqs ) ), "12 Odd Harmonics", n + 1 );
More harmonics help square it upMore harmonics help square it upMore harmonics help square it upMore harmonics help square it upより多くの高調波がバランスを整えるのに役立ちます
// multiply class
Define Class(
"multiply",
m_a = {};
_init_ = Method( {a, b = Empty()},
If( Is Empty( b ),
For( i = 1, i <= N Items( a ), i += 1,
Insert Into( m_a, v( a[i] ) )
),
m_a[1] = v( a );
m_a[2] = v( b );
)
);
next = Method( {},
result = m_a[1]:next();
For( i = 2, i <= N Items( m_a ), i += 1,
result = result :*</img> m_a[i]:next()
);
result;
);
);
// multiply two waveforms
n = 1000;
freq1 = New Object( Sin( .1, 1 ) );
freq2 = New Object( Sin( 2 * Pi() / n, 1 ) );
prod = New Object( Multiply( freq1, freq2 ) );
gr( ctr(), prod, "multiply", n + 1 );
Multiply two frequencies; the lower frequency creates the envelope.Multiply two frequencies; the lower frequency creates the envelope.Multiply two frequencies; the lower frequency creates the envelope.Multiply two frequencies; the lower frequency creates the envelope.2 つの周波数を乗算します。低い周波数はエンベロープを作成します。
// similar, but control amplitude of freq1 using another sin wave
n = 1000;
freq2 = New Object( Sin( 2 * Pi() / n, 1 ) ); // lo freq
freq1 = New Object( Sin( .1, freq2 ) ); // hi freq, control amplitude with freq2
gr( ctr(), freq1, "amp is sin", n + 1 );
Alternatively, control the amplitude of the higher frequency using the lower frequency.Alternatively, control the amplitude of the higher frequency using the lower frequency.Alternatively, control the amplitude of the higher frequency using the lower frequency.Alternatively, control the amplitude of the higher frequency using the lower frequency.あるいは、低い周波数を使用して高い周波数の振幅を制御します。
最後に、奇数高調波周波数の行列を保持する vwrap を作成し、行列を合計してスカラーにする新しいクラスを作成します。
// try a matrix...use v(...) to make a vwrap to hold the matrix
n = 200;
mat = v( ((1 :: 49 :: 2) * (2 * Pi() / n)) );
// add the sin wrapper. sinmat:next() returns a row vector of 5 sin values
sinmat = New Object( Sin( mat, 1 / (1 :: 49 :: 2) ) );
// matrixSum assumes the argument class is returning a matrix and returns the scalar sum
Define Class(
"matrixSum",
m_mat = .;
_init_ = Method( {mat},
m_mat = v( mat )
);
next = Method( {},
Sum( m_mat:next() )
);
);
gr( ctr(), New Object( matrixSum( sinmat ) ), "25 Odd Harmonics", n + 1 );
It will take a lot more harmonics to really reduce the over-shoot and the ripples.It will take a lot more harmonics to really reduce the over-shoot and the ripples.It will take a lot more harmonics to really reduce the over-shoot and the ripples.It will take a lot more harmonics to really reduce the over-shoot and the ripples.オーバーシュートとリップルを実際に低減するには、より多くの高調波が必要になります。
良いドキュメント: https://www.jmp.com/support/help/en/15.1/index.shtml#page/jmp/classes.shtml