Re: Pasar mensajes a "esto" dentro de la definición de claseDe forma predeterminada, JMP no proporciona buenas formas de consultar los pseudo-espacios de nombres directamente (ya sea ventana, este, cuadro, etc.).
Para las clases, puede pensar en crear un contenedor para construir clases; ese contenedor puede crear la función de generador de instancias y, durante esa generación de instancias, puede darle a la clase una referencia circular (tenga en cuenta que esto puede provocar pérdidas de memoria) -- asegúrese de crear un sistema de seguimiento y proporcionar/llamar a un método de eliminación cuando la clase deba eliminarse para eliminar las referencias circulares y demás.
Aquí hay un ejemplo:
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 );Sin embargo, tenga en cuenta que las clases JMP son solo espacios de nombres glorificados con funciones adjuntas (espacios de nombres donde las funciones adjuntas saben en qué espacio de nombres se encuentran).Puede hacer algo bastante similar con solo espacios de nombres regulares y metaprogramación.Y con los espacios de nombres regulares, JMP no arrojará errores superfluos sobre no poder acceder a los métodos de clase dentro de las funciones y demás.
Pasar mensajes a "esto" dentro de la definición de clase¿Es posible pasar un mensaje a la instancia de una clase desde dentro de un método?
Aquí hay un ejemplo de lo que estoy tratando de hacer:
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);Sospeché que podría necesitar escribir explícitamente "este << Insertar", pero eso produce un error diferente:
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);También consideré llamar explícitamente a Enviar (no se puede agregar el método) y esto: Enviar (no se puede resolver el nombre Enviar).
También consideré llamar directamente a esto: Insertar (no puede resolver el nombre Insertar) e Insertar (agrega con éxito el método blah, pero no logra sondear correctamente el mecanismo de llamada, por lo que no se pasan argumentos al método).
Motivación:
Estoy haciendo esto porque estoy tratando de crear automáticamente métodos getter y setter para una lista de propiedades de clase.Idealmente, podré hacer lo siguiente:
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));
Modelado Estadístico AvanzadoAutomatización y secuencias de comandosIngeniería de Calidad y ProcesosRe: Pasar mensajes a "esto" dentro de la definición de claseEste parece ser el tipo de solución que JSL te obliga a hacer.
Hay un lenguaje de programación de parodia llamado "DreamBerd" que se burla de los paradigmas de programación.Esta solución es muy similar a cómo el lenguaje de parodia maneja las clases, pero logra ser aún más complejo.
(No digo que esto sea su culpa, es solo una consecuencia de las limitaciones en JSL).
https://github.com/TodePond/DreamBerd
ClasesPuede crear clases, pero solo puede crear una instancia de ellas. Esto no debería afectar la forma en que trabajan la mayoría de los programadores orientados a objetos.
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!Así es como podrías hacer esto:
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: Pasar mensajes a "esto" dentro de la definición de claseCreo que esto podría manejarse mejor con el paso de mensajes personalizados, pero realmente no puedo encontrar ninguna documentación sobre cómo hacerlo.Por lo que puedo decir, no hay información sobre la implementación de sus propios mensajes.
Re: Pasar mensajes a "esto" dentro de la definición de claseLos mensajes solo llaman a métodos para clases; técnicamente, no puede llamar a una función con argumentos a través de un mensaje, pero dado que los métodos en las clases JSL son expresiones, el resultado de la llamada del mensaje es una función invocable.Para todos los efectos, puede simplemente llamar al método de clase a través de un mensaje.
Observe la línea Mostrar( clx << Agregar( cly ) ); llamando al Agregar método a través de un mensaje.
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: Pasar mensajes a "esto" dentro de la definición de claseSigo olvidando que mientras JSL toma prestado de los mejores (en este caso paso de mensajes en smalltalk ), nunca capta del todo lo que tenía de especial el original.