끝에 클래스 정의를 사용하는 방법 JSL 클래스 인스턴스를 복사하기가 어렵다는 흥미로운 점이 있습니다. X가 인스턴스를 참조하면 Y = X는 Y와 X를 모두 만듭니다. 보내다 ~로 같은 예. 인스턴스를 사용자 정의 함수에 전달할 때도 같은 일이 발생합니다. 함수의 값은 아니 인스턴스의 사본; 그것 참조 ~로 같은 예. 따라서 함수 내에서 인스턴스를 변경하면 호출자도 변경됩니다. 함수에 행렬을 전달하고 함수에서 행렬을 수정 한 경우 호출자의 기대 부 JSL은 값으로 사용자 함수에 인수를 전달한다는 것을 알고 있습니다.
JMP는 사본을 만들어 인수를 전달하지만 ...
행렬이 복사되므로 함수 내부의 행렬이 원본이 아닌 복사본으로 변경됩니다. 큰 검은 색 참조 점도 복사되지만 참조하는 객체는 복사되지 않습니다. 이 그림을 보지 못했기 때문에 초보자 자바 프로그래머에게는 많은 두통이 발생합니다. 함수 내에서 변수에 대해 매우 다른 두 가지 일을 할 수 있습니다 ㅏ .
- a : set (42)와 같은 메소드를 호출 할 수 있습니다.
- a = 42와 같은 값을 지정할 수 있습니다.
(1)의 경우 아가일 3에서 42 사이의 객체 값. 이것은 아마도 당신이해야 할 일입니다. (2)의 경우 옆에있는 큰 검은 점을 덮어 씁니다. ㅏ 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))를 작성하는 것은 약간 추악하기 때문에 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 값의 행렬을 만들고 보이지 않는 테이블을 만들고 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 (...)로 전달되었습니다.
0에서 시작하는 5 단계에 대해 병렬로 실행되는 2 개의 카운터.
이제 다른 점이 있습니다. 카운터의 비율을 다른 카운터로 만들어 봅시다.
// this variation begins to show the power of composition
gr( ctr(), ctr( ctr() ), "count up B (first step is 0)", 5 );
속도 카운터의 첫 번째 결과가 0이므로 첫 번째 단계는 0입니다.
이 그래프의 Y 축은 두 카운터의 기능 구성을 사용합니다. sin () 클래스를 추가 할 수 있습니다.
// sin() wrapper class
Define Class(
"sin",
m_rate = .; // 0<STEP><PI. m_amp=".;"></PI.></STEP>
Sin은 상수 또는 다른 클래스 인스턴스에 의해 결정된 주파수 및 진폭에서 무한 사인파를 생성합니다. 또한 내부 위치를 유지합니다. 의견에서 더 많은 생각이 필요할 수 있지만이 데모에서는 효과가 있다고 말할 수 있습니다. 단일 사이클 파형이 있습니다.
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))
);오프셋 도우미를 사용하면 초기 0 단계를 가진 초기 그래프 중 하나를 초기 단계 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/en/15.1/index.shtml#page/jmp/classes.shtml