Re : Passer des messages à "ceci" dans la définition de la classePar défaut, JMP ne fournit pas de moyens pratiques pour interroger directement les pseudo-espaces de noms (qu'il s'agisse de window, this, box, etc.).
Pour les classes, vous pourriez penser à créer un wrapper pour construire des classes - ce wrapper peut ensuite créer la fonction de générateur d'instance, et pendant cette génération d'instance, vous pouvez donner à la classe une référence circulaire (notez que cela peut conduire à des fuites de mémoire) -- assurez-vous de créer un système de suivi et fournissez/appelez une méthode de suppression lorsque la classe doit être supprimée pour supprimer les références circulaires et autres.
Voici un exemple :
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 );Notez cependant que les classes JMP ne sont que des espaces de noms glorifiés avec des fonctions attachées (espaces de noms où les fonctions attachées savent dans quel espace de noms elles se trouvent).Vous pouvez faire quelque chose d'assez similaire avec juste des espaces de noms réguliers et une méta-programmation.Et avec les espaces de noms réguliers, JMP ne lancera pas d'erreurs superflues sur l'impossibilité d'accéder aux méthodes de classe dans les fonctions et ainsi de suite.
Passer des messages à "ceci" dans la définition de classeEst-il possible de passer un message à l'instance d'une classe depuis une méthode ?
Voici un exemple de ce que j'essaye de faire :
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);Je soupçonnais que j'aurais peut-être besoin d'écrire explicitement "this << Insert", mais cela génère une erreur différente :
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);J'ai également envisagé d'appeler explicitement Send (ne parvient pas à ajouter la méthode) et this:Send (ne parvient pas à résoudre le nom Send).
J'ai également envisagé d'appeler directement this:Insert (ne parvient pas à résoudre le nom Insert) et Insert (ajoute avec succès la méthode blah, mais ne parvient pas à sonder correctement le mécanisme d'appel, donc aucun argument n'est transmis à la méthode).
Motivation:
Je fais cela parce que j'essaie de créer automatiquement des méthodes getter et setter pour une liste de propriétés de classe.Idéalement, je serai capable de faire ce qui suit :
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));
Modélisation statistique avancéeAutomatisation et scriptIngénierie de la qualité et des procédésRe : Passer des messages à "ceci" dans la définition de la classeCela semble être le genre de solution de contournement que JSL vous oblige à faire.
Il existe un langage de programmation parodique appelé "DreamBerd" qui se moque des paradigmes de programmation.Cette solution de contournement est très similaire à la façon dont le langage parodique gère les classes, mais parvient à être encore plus complexe.
(Je ne dis pas que c'est de votre faute, c'est juste une conséquence des limitations de JSL).
https://github.com/TodePond/DreamBerd
Des classesVous pouvez créer des classes, mais vous ne pouvez en créer qu'une seule instance. Cela ne devrait pas affecter le fonctionnement de la plupart des programmeurs orientés objet.
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!Voici comment vous pourriez procéder :
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 : Passer des messages à "ceci" dans la définition de la classeJe pense que cela pourrait être mieux géré avec le passage de messages personnalisés, mais je ne trouve pas vraiment de documentation sur la façon de le faire.Autant que je sache, il n'y a aucune information sur la mise en œuvre de vos propres messages.
Re : Passer des messages à "ceci" dans la définition de la classeLes messages appellent simplement des méthodes pour les classes - techniquement, vous ne pouvez pas appeler une fonction avec des arguments via un message, mais comme les méthodes des classes JSL sont des expressions, le résultat de l'appel de message est une fonction appelable.À toutes fins utiles, vous pouvez simplement appeler la méthode de classe via un message.
Remarquez la ligne Show( clx << Add( cly ) ); appelant le Ajouter méthode via un message.
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 : Passer des messages à "ceci" dans la définition de la classeJ'oublie toujours que même si JSL emprunte aux meilleurs (dans ce cas message passant en smalltalk ), il ne capture jamais tout à fait ce qu'il y avait de spécial dans l'original.