Re: クラス定義内の "this" にメッセージを渡すデフォルトでは、JMP は擬似名前空間 (window、this、box など) を直接クエリする優れた方法を提供しません。
クラスの場合は、クラスを構築するためのラッパーを作成することを考えるかもしれません。そのラッパーはインスタンス ジェネレーター関数を作成でき、そのインスタンスの生成中にクラスに循環参照を与えることができます (メモリ リークが発生する可能性があることに注意してください)。 -- 循環参照などを削除するためにクラスを削除する必要がある場合は、追跡システムを作成し、デリーター メソッドを提供または呼び出してください。
以下に例を示します。
Names Default to Here( 1 );
New Namespace( "class" );
class:Get Init Args = Function( {_class},
{Default Local},
For( i = 1, i <= N Items( _class ), i++,
If( Head Name( Arg( _class, i ) ) == "Glue",
For( j = 1, j <= N Arg( Arg( _class, i ) ), j++,
If( As Name( Head Name( Arg( Arg( Arg( _class, i ), j ), 1 ) ) ) == As Name( "_create_" ),
Return( Arg( Arg( Arg( Arg( _class, i ), j ), 2 ), 1 ) )
)
)
)
);
Return( {} )
);
class:Define Class = Function( {_class},
{Default Local},
class = Expr( Define Class() );
Summation( i = 1, N Arg( _class ),
Insert Into( class, Arg( _class, i ) )
);
init args = class:Get Init Args( _class );
init redirects = Expr( __cl:_create_() );
Summation( i = 1, N Items( init args ),
If( Head Name( Arg( init args, i ) ) == "Assign",
Insert Into( init redirects, Eval Expr( Name Expr( Expr( Arg( Arg( init args, i ), 1 ) ) ) ) )
,
Insert Into( init redirects, Eval Expr( Name Expr( Expr( Arg( init args, i ) ) ) ) )
)
);
Eval( class );
ns = Namespace( "class" );
Eval( Substitute( Expr(
ns[__class__] = Function( __args__,
{__cl = New Object( __class__ )},
__cl:self = __cl;
__class_call__;
__cl
)
),
Expr( __class__ ), Arg( _class, 1 ),
Expr( __args__ ), init args,
Expr( __class_call__ ), Name Expr( init redirects )
) );
0
);
class:Define Class({
"example",
_init_ = Method( {}, 1 );
_create_ = Method( {assocArray},
For Each( {{key, setter}, _}, assocArray,
self << Insert( key, Eval Expr( Method( {value}, self:TrySetProperty( Expr( key ), value, Expr( setter ) ) ) ) )
)
);
Try Set Property = Method( {parameter, value, expression If Changed},
Match( value,
., ., //Do nothing if missing value
,
self[parameter], . //Do nothing if unchanged value
,
self[paremeter] = value; //Otherwise update the value
Eval( expression If Changed ); //and eval the expression
);
);
show = Function( {name},
show( name )
)
});
//show( namespace( "class" ) );
cls = class:example( ["A" => expr( self:show( "EXPLETIVE" ) ), "B" => Expr( thing 2 )] );
show( cls << get keys );ただし、JMP クラスは関数が付加された単なる美化された名前空間 (付加された関数がどの名前空間にあるかを認識している名前空間) であることに注意してください。通常の名前空間とメタプログラミングだけで、非常に似たようなことができます。また、通常の名前空間を使用すると、JMP は関数内でクラス メソッドにアクセスできないなどの余計なエラーをスローしません。
クラス定義内の「this」にメッセージを渡すメソッド内からクラスのインスタンスにメッセージを渡すことはできますか?
これが私がやろうとしていることの例です:
Define Class(
"example",
x=1;
test = Method( {name, method},
<< Insert(name, method);
);
);
t = New Object( example());
// This fails to insert the blah method
t:test("blah", Method({y}, show("Blah " || char(x) || char(y))));
t:blah(6);
//This succeeds in inserting and calling the blah method
t << Insert("blah", Method({y}, show("Blah " || char(x) || char(y))));
t:blah(6);「this << Insert」を明示的に記述する必要があるのではないかと考えましたが、別のエラーが発生します。
Define Class(
"example",
x=1;
test = Method( {name, method},
<STRONG>this << Insert(name, method);</STRONG>
);
);
t = New Object( example());
// This fails because "send expects scriptable object"
t:test("blah", Method({y}, show("Blah " || char(x) || char(y));));
t:blah(6);また、Send (メソッドの追加に失敗) と this:Send (Send という名前の解決に失敗) を明示的に呼び出すことも検討しました。
また、これを直接呼び出すことも検討しました。Insert (Insert という名前の解決に失敗します) と Insert (何とかメソッドの追加には成功しますが、呼び出しメカニズムを正しく実装できないため、メソッドに引数が渡されません)。
モチベーション:
これを行うのは、クラス プロパティのリストのゲッター メソッドとセッター メソッドを自動的に作成しようとしているためです。理想的には、次のことができるようになります。
Define Class(
"example",
_init_ = Method( {assocArray},
For Each({property, updateMethod}, assocArray,
Insert(key, Eval Expr(Method({value}, TrySetProperty(Expr(property), value, Expr(updateMethod)))));
);
);
TrySetProperty=Method({parameter, value, expressionIfChanged},
match(value,
., ., //Do nothing if missing value
this << Get Value(parameter), ., //Do nothing if unchanged value
this << Insert(parameter, value); //Otherwise update the value
Eval(expressionIfChanged); //and eval the expression
);
);
);
properties = Associative Array({{"prop1", Expr(ThingToDoOnUpdate1)},{"prop2", Expr(ThingToDoOnUpdate2)}});
t = New Object( example(properties));
高度な統計モデリング自動化とスクリプト作成品質およびプロセスエンジニアリングRe: クラス定義内の "this" にメッセージを渡すこれは、JSL が強制する一種の回避策のようです。
プログラミングのパラダイムをからかう「DreamBerd」というパロディプログラミング言語があります。この回避策は、パロディ言語がクラスを処理する方法と非常に似ていますが、さらに複雑になります。
(これがあなたのせいだと言っているのではなく、JSL の制限の結果にすぎません)。
https://github.com/TodePond/DreamBerd
クラスクラスを作成できますが、作成できるインスタンスは 1 つだけです。 これは、ほとんどのオブジェクト指向プログラマの作業方法に影響を与えることはありません。
class Player {
const var health = 10!
}
const var player1 = new Player()!
const var player2 = new Player()! //Error: Can't have more than one 'Player' instance!これを行う方法は次のとおりです。
class PlayerMaker {
function makePlayer() => {
class Player {
const var health = 10!
}
const const player = new Player()!
return player!
}
}
const const playerMaker = new PlayerMaker()!
const var player1 = playerMaker.makePlayer()!
const var player2 = playerMaker.makePlayer()!
Re: クラス定義内の "this" にメッセージを渡すこれはカスタム メッセージ パッシングを使用するとより適切に処理できると思いますが、実際にそれを行う方法についてのドキュメントは見つかりません。私の知る限り、独自のメッセージの実装に関する情報はありません。
Re: クラス定義内の "this" にメッセージを渡すメッセージはクラスのメソッドを呼び出すだけです。技術的には、メッセージを介して引数を指定して関数を呼び出すことはできませんが、JSL クラスのメソッドは式であるため、メッセージ呼び出しの結果は呼び出し可能な関数になります。どのような目的であっても、メッセージ経由でクラス メソッドを呼び出すことができます。
線に注目してくださいShow( clx << Add( cly ) );を呼び出す追加メッセージによる方法。
Names Default To Here( 1 );
Define Class(
"complex",
real = 0;
imag = 0;
_init_ = Method( {a, b},
real = a;
imag = b;
);
Add = Method( {y},
PRINT( "ADDING" );
New Object( complex( real + y:real, imag + y:imag ) )
);
Sub = Method( {y},
New Object( complex( real - y:real, imag - y:imag ) )
);
Mul = Method( {y},
New Object( complex( real * y:real - imag * y:imag, imag * y:real + real * y:imag ) )
);
Div = Method( {y},
t = New Object( complex( 0, 0 ) );
mag2 = y:Magsq();
t:real = real * y:real + imag * y:imag;
t:imag = imag * y:real + real * y:imag;
t:real = t:real / mag2;
t:imag = t:imag / mag2;
t;
);
Magsq = Method( {},
real * real + imag * imag
);
Mag = Method( {},
Sqrt( real * real + imag * imag )
);
_to string_ = Method( {},
Char( real ) || " + " || Char( imag ) || "i"
);
_show_ = _to string_;
);
clx = New Object( complex( 1, 2 ) );
cly = New Object( complex( 2, 3 ) );
Show( clx << Add( cly ) );
clx << Delete;
cly << Delete;
Delete Classes( "complex" );Re: クラス定義内の "this" にメッセージを渡すJSL は最高のものを借用しているにもかかわらず、私はそのことを忘れがちです (この場合、 smalltalk でのメッセージ受け渡し)、オリジナルの特別な点を完全には捉えていません。