#1184 closed defect (fixed)
PutName and new objects
Reported by: | Pedro Gea | Owned by: | Víctor de Buen Remiro |
---|---|---|---|
Priority: | high | Milestone: | Mantainance |
Component: | Kernel | Version: | head |
Severity: | critical | Keywords: | |
Cc: |
Description
La función PutName
no puede utilizarse sobre objetos sin un nombre previo o definidos en el argumento. Por ejemplo:
Real PutName("valor", 2); //ERROR: [] 2 no es un objeto valido para el tipo Real. //Warning: [] La función PutName ha fallado en : // PutName("valor", 2)
No sé si esta limitación tiene alguna intencionalidad o podría resolverse.
Habitualmente para ello utilizo una función auxiliar con el siguiente código:
Anything PutName2(Text name, Anything object) { Anything object_ = object; PutName(name, object_) };
de la que quizá podría prescindir.
También es bastante común, para asignar un nombre ver código como el siguiente:
Eval(Grammar(object)<<" "<<name<<" = object");
Aprovecho para comentar algunos otros detalles de esta función como que me confunden un poco.
Parece que la función asigna el nombre localmente pero lo comprueba globalmente.
Esto no da error cuando lo esperaría:
Real { Real a = 1; Real b = 2; Real PutName("a", b); Real a }; //> 2
Sin embargo esto sí lo da y no lo esperaba:
Real a = 1; Real { Real b = 2; Real PutName("a", b); Real a }; //ERROR: [] No se puede hacer PutName : a existe todavía
Pero sin embargo la variable renombrada no es accesible globalmente:
Real a = 1; Real { Real b = 2; Real PutName("c", b); Real c }; Real c; //ERROR: [] c no es un objeto valido para el tipo Real.
quizá porque ya no existe.
Para evitar esto suelo usar una función auxiliar
Anything PutLocalName(Text name, Anything object) { Eval(Grammar(object)<<" "<<name<<" = object") };
aunque quizá lo mejor es definir bien el comportamiento de PutName
.
También sería necesario considerar qué nombres son aceptables, ya que ahora es admisible casi cualquier tipo de nombre, aunque vuelva al objeto inaccesible. Por ejemplo:
Real a = 1; Real PutName("$5./* @", a);
Aunque solucionar esto último pueda ser delicado, porque creo que se está usando del siguiente modo:
Set conjunto = Copy(Empty); Real a = 1; Set Append(conjunto, [[ PutName("$5./* @", a) ]], True); Real FindIndexByName(conjunto, "$5./* @"); //> 1
Change History (7)
comment:1 Changed 14 years ago by
comment:2 Changed 14 years ago by
Bien, la discusión me sirve para aclararme un poco. Creo que entiendo mejor la diferencia entre PutName
y la función que ando buscando.
La función PutName sirve para cambiar el nombre a una variable existente y yo ando buscando una función que me cambie la variable por otra igual o la misma (esto es algo delicado) con el mismo nombre.
El usar RenamedCopy
no me gusta porque copiar en TOL (Copy
) no es lo mismo. Por ejemplo en el caso de un nameblock lo que quiero es una nueva referencia al objeto con otro nombre (el mismo objeto) y no una copia (otro objeto igual) con otro nombre. En los objetos que se asignan por valor, claro, no existe esta diferencia que parece tan sutil. Yo optaría más por utilizar algo como ReturnWithName
o simplemente WithName
o algo así.
En la mayor parte de los casos, sin embargo, el uso de PutName
o WithName
es un tanto indiferente. Pongo un ejemplo:
NameBlock CreaAlgoConNombre(Text name, Real valor, Real valor2) { NameBlock algo = [[ Real v1 = valor; Real v2 = valor2 ]]; PutName(name, algo) }; // Esta función podría usarse luego para crear objetos que estarían // indexados en un conjunto contenedor o algo así.
En principio, parece que lo mismo da cambiarle el nombre al objeto algo
(como se ha hecho) que crear una copia (referencia) con otro nombre, pues será la única que sobreviva.
Digamos que resueltas las dudas, sólo quedan dos cuestiones por resolver:
- La cuestión sobre el ámbito de
PutName
que parece que no es acertado. - La cuestión de los nombres válidos, que creo que no tiene ninguna urgencia.
comment:3 Changed 14 years ago by
La cuestión sobre el ámbito como ya he dicho no es soluble, es un efecto secundario debido a un uso indebido. Simplemente no hay que hacerlo.
Sobre los nombres válidos tampoco hay nada que hacer. El PutName no es para interactuar con el reconocedor. Si le pones un nombre no válido pues no se puede usar luego en el lenguaje, pero es que el nombre tiene otras utilidades estéticas e informativas y es cuestión de cada cuál lo que quiera hacer con eso.
comment:4 Changed 14 years ago by
Respecto al ámbito, no entiendo que se comporte así y no se pueda solucionar, pero bueno, puedo marginar esa función y ya está, porque no voy a implementar una función que fallará si por casualidad el usuario ha creado una variable global con el mismo nombre de la que yo quiero cambiar.
Repito el ejemplo, porque me confunde que sea admita así, porque en ese caso la función no me vale ni con motivos decorativos, ni para indexar ni nada:
Real a = 1; Real { Real b = 2; Real PutName("a", b); // ... Real ? }; //ERROR: [] No se puede hacer PutName : a existe todavía
comment:7 Changed 14 years ago by
Ya está arreglado. Se buscaba una variable con el nombre solicitado y se daba el error si se hallaba, pero antes de eso hay que comprobar si está en el mismo nivel o es de un ámbito superior en cuyo caso no hay problema.
En el caso del ejemplo ya no da error y tanto da si se devuelve el a local como el b local, que sigue funcionando pues el árbol sintáctico ha sido generado ya previamente
Real a = 1; Real a.2 = { Real b = 2; Real PutName("a", b); a }; Real ok = a.2==2;
Real a = 1; Real a.2 = { Real b = 2; Real PutName("a", b); b }; Real ok = a.2==2;
No tiene ningún sentido poner nombre a una constante literal temporal aunque imagino que querías ilustrar otra cosa.
Sí tendría sentido hacerlo a constantes literales capturadas en un Set, que es el verdadero objetivo de PutName
De hecho alguna vez me he arrepentido de no haberla creado así
Pero lo hecho hecho está y no hay forma de cambiarlo ahora con cientos de miles de líneas que lo usan por ahí.
El uso de PutName no debe interaccionar nunca con el reconocedor sintáctico. No se debe cambiar el nombre de variables usadas en el lenguaje, ni locales ni globales ni miembros. Los efectos secundarios de PutName son inevitables si se hace un mal uso de esta funcionalidad.
Digamos que sólo debe cambiar el nombre de elementos de conjuntos no accesibles desde el lenguaje y para alguno de estos motivos:
Tanto el uso Eval como el PutName2 que propones no cambian el nombre de nada sino que crean un nuevo objeto copia de otro que tiene el nombre deseado, por lo que no hay ninguna restricción al respecto. Yo lo llamaría RenamedCopy.
Lo único que se puede hacer al respecto es incorporar estas anotaciones a la descripción de PutName. Lo pondré en castellano y a ver si alguien me lo traduce al inglés porque es demasiado complicado para mi tarzanesco nivel anglófono.