Ri: Passare messaggi a "questo" all'interno della definizione della classePer impostazione predefinita, JMP non fornisce modi carini per interrogare direttamente gli pseudo-spazi dei nomi (che si tratti di finestra, questo, box, ecc.).
Per le classi, potresti pensare di creare un wrapper per la costruzione di classi: quel wrapper può quindi creare la funzione del generatore di istanze e, durante la generazione di quell'istanza, puoi dare alla classe un riferimento circolare (nota che ciò può portare a perdite di memoria) - assicurati di creare un sistema di tracciamento e di fornire/chiamare un metodo di eliminazione quando la classe deve essere eliminata per rimuovere i riferimenti circolari e simili.
Ecco un esempio:
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 );Si noti tuttavia che le classi JMP sono solo spazi dei nomi glorificati con funzioni associate (spazi dei nomi in cui le funzioni associate sono a conoscenza dello spazio dei nomi in cui si trovano).Puoi fare qualcosa di abbastanza simile con solo normali spazi dei nomi e meta-programmazione.E con i normali spazi dei nomi JMP non genererà errori superflui sull'impossibilità di accedere ai metodi di classe all'interno di funzioni e quant'altro.
Passare messaggi a "questo" all'interno della definizione della classeÈ possibile passare un messaggio all'istanza di una classe dall'interno di un metodo?
Ecco un esempio di quello che sto cercando di fare:
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);Sospettavo che avrei potuto aver bisogno di scrivere esplicitamente "this << Insert", ma questo produce un errore diverso:
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);Ho anche considerato di chiamare esplicitamente Send (non riesce ad aggiungere il metodo) e this:Send (non riesce a risolvere il nome Send).
Ho anche considerato di chiamare direttamente this:Insert (non riesce a risolvere il nome Insert) e Insert (aggiunge con successo il metodo blah, ma non riesce a scandagliare correttamente il meccanismo di chiamata, quindi nessun argomento viene passato nel metodo).
Motivazione:
Lo sto facendo perché sto cercando di creare automaticamente metodi getter e setter per un elenco di proprietà di classe.Idealmente, sarò in grado di fare quanto segue:
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));
Modellazione statistica avanzataAutomazione e scriptingQualità e ingegneria di processoRi: Passare messaggi a "questo" all'interno della definizione della classeQuesto sembra essere il tipo di soluzione alternativa che JSL ti costringe a fare.
Esiste un linguaggio di programmazione parodia chiamato "DreamBerd" che prende in giro i paradigmi di programmazione.Questa soluzione alternativa è molto simile al modo in cui il linguaggio della parodia gestisce le classi, ma riesce a essere ancora più complessa.
(Non dire che è colpa tua, è solo una conseguenza delle limitazioni in JSL).
https://github.com/TodePond/DreamBerd
ClassiPuoi creare classi, ma puoi crearne solo un'istanza. Ciò non dovrebbe influire sul funzionamento della maggior parte dei programmatori orientati agli oggetti.
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!Ecco come potresti farlo:
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()!
Ri: Passare messaggi a "questo" all'interno della definizione della classePenso che questo potrebbe essere gestito meglio con il passaggio di messaggi personalizzati, ma non riesco davvero a trovare alcuna documentazione su come farlo effettivamente.Per quanto ne so, non ci sono informazioni sull'implementazione dei tuoi messaggi.
Ri: Passare messaggi a "questo" all'interno della definizione della classeI messaggi chiamano solo metodi per le classi: tecnicamente non puoi chiamare una funzione con argomenti tramite un messaggio, ma poiché i metodi nelle classi JSL sono espressioni, il risultato della chiamata del messaggio è una funzione richiamabile.A tutti gli effetti, puoi semplicemente chiamare il metodo della classe tramite un messaggio.
Notare la linea Mostra( clx << Aggiungi( cly ) ); chiamando il Aggiungere metodo tramite un messaggio.
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" );Ri: Passare messaggi a "questo" all'interno della definizione della classeContinuo a dimenticare che mentre JSL prende in prestito dai migliori (in questo caso messaggio che passa in chiacchiere ), non cattura mai del tutto ciò che era speciale nell'originale.