回复:在類定義中將消息傳遞給“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)。
我還考慮過直接調用 this:Insert(無法解析名稱 Insert)和 Insert(成功添加了 blah 方法,但未能正確探測調用機制,因此沒有參數傳遞到方法中)。
動機:
我這樣做是因為我試圖為類屬性列表自動創建 getter 和 setter 方法。理想情況下,我將能夠做到以下幾點:
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));
高級統計建模自動化和腳本質量與工藝工程回复:在類定義中將消息傳遞給“this”這似乎確實是 JSL 強制您執行的解決方法。
有一種模仿編程語言稱為“DreamBerd”,它取笑編程範例。這種解決方法與模仿語言處理類的方式非常相似,但設法變得更加複雜。
(並不是說這是你的錯,這只是 JSL 限制的結果)。
https://github.com/TodePond/DreamBerd
班級您可以創建類,但您只能創建它們的一個實例。 這不應該影響大多數面向對象的程序員的工作方式。
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()!
回复:在類定義中將消息傳遞給“this”我認為通過自定義消息傳遞可以更好地處理這個問題,但我真的找不到任何關於如何真正做到這一點的文檔。據我所知,沒有關於實現您自己的消息的信息。
回复:在類定義中將消息傳遞給“this”消息只是調用類的方法——從技術上講,您不能通過消息調用帶參數的函數,但由於 JSL 類中的方法是表達式,消息調用的結果是一個可調用函數。出於所有意圖和目的,您可以通過消息調用類方法。
注意這條線顯示(clx << 添加(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" );回复:在類定義中將消息傳遞給“this”我一直忘記,雖然 JSL 借鑒了最好的(在這種情況下smalltalk中的消息傳遞), 它從來沒有完全捕捉到原作的特別之處。