在......的最後如何使用定義類我暗示關於JSL類實例很難復制有一些有趣的事情。如果X引用實例,則Y = X使得Y和X 參考到相同實例。將實例傳遞給用戶定義的函數時,也會發生同樣的事情:該函數的值為不實例的副本;它指到相同實例。因此,在函數內部更改實例也會為調用方更改它。如果您曾經將矩陣傳遞給函數並在函數中對其進行了修改,請期待調用者的複製要進行更新,您知道JSL通過值將參數傳遞給用戶函數。
JMP通過複製來傳遞參數,但是...
請注意,矩陣是複制的,因此對函數內部矩陣的更改是對副本的更改,而不是對原始內容的更改。請注意,黑色的大參考點也會被複製,但不會被複製。這使剛開始的JAVA程序員很頭疼,因為他們沒有看到這張圖片。在函數中,您可以做兩個非常不同的事情來變量一個 。
- 您可以調用一個方法,例如a:set(42);
- 您可以分配一個值,例如a = 42;
如果(1)您更改了亞皆老街對象的值,從3到42。這可能就是您的意思。在情況(2)中,您覆蓋了旁邊的大黑點一個與42。您可能並不打算這樣做。
以下代碼使用保留對其他對象的引用的對象。所有對像都有一個next()方法,因此可以用有趣的方式來組成對象。next()方法產生值序列中的下一個值。一些對象表示一個常數,並且始終產生相同的下一個值。其他對象(如添加對象)具有其他兩個對象(+運算符的左側和右側)。Add:next()調用left:next()和right:next()並添加兩個答案。
完整的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))有點醜陋,所以讓我們也創建一個輔助函數來製作Vwraps。
// 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個值的矩陣,並創建一個不可見的表,並運行Graph Builder,並在不再需要隱藏表時使用了一些魔術方法將其關閉。讓我們嘗試一下。
gr( 13, 42, "Value 13,42", 1 );
單點,x = 13,y = 42
等等,它將變得更好...讓我們創建一個計數器類,該類將返回0、1、2、3,... 在對next()的連續調用中。
// 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軸的gr(...)。
兩個計數器並行運行,從零開始五個步驟。
現在,換一種方式:讓計數器的匯率成為另一個計數器。
// this variation begins to show the power of composition
gr( ctr(), ctr( ctr() ), "count up B (first step is 0)", 5 );
第一步是零,因為速率計數器的第一個結果是零。
該圖的Y軸使用兩個計數器的功能組合。讓我們添加一個sin()類。
// sin() wrapper class
Define Class(
"sin",
m_rate = .; // 0<STEP><PI. m_amp=".;"></PI.></STEP>
正弦波會產生無限的正弦波,其頻率和振幅由常數或其他類別實例確定。它還保持內部位置。您可以從評論中看出,可能需要更多考慮,但是它適用於此演示。這是一個單週期波形。
gr( ctr(), New Object( Sin( 2 * Pi() / 100, 3 ) ), "sin()", 101 );
單週期正弦波
類似於具有另一個計數器增量的計數器,正弦波可以具有可變頻率。
gr( ctr(), New Object( Sin( New Object( Sin( .0002, 1 ) ), 3 ) ), "variable frequency", 1000 );
使用另一個正弦波的第一位來提高頻率
並且可以繪製兩個不同頻率的正弦波。
gr( New Object( Sin( 4 * Pi() / 99, 3 ) ), New Object( Sin( 6 * Pi() / 99, 3 ) ), "2X3 sin()", 100 );
簡單的整數比率構成了不錯的模式
另一個類和輔助函數;該類將一個或多個其他類添加在一起,而偏移量幫助器添加了一個常量...或另一個函數,可能是...未經測試的。
// 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))
);使用偏移幫助器,可以將具有初始零步長的早期圖形之一重做為具有一個初始步長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 );
現在所有步驟都比以前大了一個。
// 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 );
以減小的幅度求和的奇次諧波近似於一個方波。
// 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 );
更多諧波有助於將其平方
// 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 );
將兩個頻率相乘;較低的頻率產生包絡。
// 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 );
或者,使用較低頻率控制較高頻率的幅度。
最後,製作一個包含奇次諧波頻率矩陣的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 );
要真正減少過沖和紋波,將需要更多的諧波。
好的文檔: https://www.jmp.com/support/help/zh/15.1/index.shtml#page/jmp/classes.shtml