在......的最後如何使用定義類我暗示 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的程序員很頭疼,因為他們沒有見過這張圖。 在函數內,您可以對變量執行兩種截然不同的操作A 。
- 你可以調用一個方法,比如 a:set(42);
- 您可以指定一個值,例如a=42;
如果 (1) 你改變了亞皆老街對象的值從 3 到 42。 這可能就是您想要做的。在情況(2)中,您覆蓋旁邊的大黑點A與 42. 你可能不是故意這樣做的。
以下代碼使用保留對其他對象的引用的對象。 所有對像都有一個 next() 方法,因此可以以有趣的方式組合對象。 next() 方法生成值序列中的下一個值。 有些對象代表一個常量,並且總是產生相同的下一個值。 其他對象(例如 add 對象)有兩個其他對象(+ 運算符的左側和右側)。 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 是類的名稱,它包裝一個值,可以是數字或矩陣。 它有一個 setter,將拒絕它不喜歡的值,還有一個名為 next() 的 getter,用於返回序列中的下一個值。 因為寫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 個值的矩陣,創建一個不可見的表,然後運行圖形生成器,並在不再需要時使用一些魔法來關閉隱藏表。 我們來試試吧。
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 軸的兩個單獨的計數器實例被傳遞給 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.兩個計數器並行運行,從零開始執行五個步驟。
現在,做一些不同的事情:讓我們將計數器的速率設置為另一個計數器。
// 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.第一步為零,因為速率計數器的第一個結果為零。
該圖的 Y 軸使用兩個計數器的功能組合。 讓我們添加一個 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單週期正弦波
與具有另一個計數器增量的計數器類似,正弦波可以具有可變頻率。
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使用另一個正弦波的第一位來提高頻率
兩個不同頻率的正弦波可以相互繪製。
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簡單的整數比率可以創造出漂亮的圖案
另一個類和輔助函數;該類將一個或多個其他類添加在一起,並且偏移量助手添加一個常量...或另一個函數,可能...未經測試。
// 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 );
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.現在所有的台階都比以前大了一截。
// 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.將兩個頻率相乘;較低的頻率創建包絡。
// 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