close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 14 years ago

Closed 14 years ago

Last modified 14 years ago

#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 Víctor de Buen Remiro

No tiene ningún sentido poner nombre a una constante literal temporal aunque imagino que querías ilustrar otra cosa.

Real PutName("valor", 2);

Sí tendría sentido hacerlo a constantes literales capturadas en un Set, que es el verdadero objetivo de PutName

Set s = [[2,"a",y2011]];
Real PutName("s1",s[1]);
Text PutName("s2",s[2]);
Date PutName("s3",s[3]);

De hecho alguna vez me he arrepentido de no haberla creado así

Real PutElementName(Text name, Set set, Real numElem);

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:

  • A efectos decorativos, para que salgan los títulos en gráficas, tablas, etc.
  • Para poder reconocer los elementos de conjuntos sin tener que usar estructuras.
  • Para indexar por nombre y poder hacer luego búsquedas rápidas por nombre.
  • Ocasionalmente es posible querer cambiar el nombre de una variable local que ya no va a ser usada en el ámbito de creación pero que es la salida de un EvalSet o un For y va a formar parte de un Set. Es lo mismo que cambiar el nombre después y puede ser más rápido y cómodo.

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.

comment:2 Changed 14 years ago by Pedro Gea

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 Víctor de Buen Remiro

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 Pedro Gea

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:5 Changed 14 years ago by Víctor de Buen Remiro

(In [3469]) Refs #1184

comment:6 Changed 14 years ago by Víctor de Buen Remiro

Resolution: fixed
Status: newclosed

(In [3473]) Fixes #1184

comment:7 Changed 14 years ago by Víctor de Buen Remiro

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;
Note: See TracTickets for help on using tickets.