Opened 14 years ago
Closed 14 years ago
#1086 closed defect (fixed)
Funciones de conjuntos con NameBlock
Reported by: | Iván Robles | Owned by: | Víctor de Buen Remiro |
---|---|---|---|
Priority: | normal | Milestone: | Mantainance |
Component: | Kernel | Version: | |
Severity: | normal | Keywords: | |
Cc: |
Description
Buenos días,
el siguiente código hace que se caiga tol
Set a = Ois.Load("C:/ejemploNameBlock.oza"); Real (setNameBlock[1]<:setNameBlock);
Con el Unique también pasa.
Creo que el problema viene de que no esta muy claro como se comparan nameblock, o incluso no se deberian comparar. No se.
Lo subo para evitar que se caiga Tol
Change History (11)
comment:1 Changed 14 years ago by
comment:2 Changed 14 years ago by
Estas funciones de conjuntos (Unique
y el operador <:
) fallan también en otras circunstancias, por ejemplo:
Real ? <: [[1,2,?]]; Set Unique([[1,2,?,2,?]]);
quizá merece la pena revisarlas con cuidado.
Respecto a los NameBlock
(y quizá también otros para otros objetos con referencias) yo propondría la comparación de dichas referencias, de modo que se compara si son "el mismo" y no si son "iguales".
Si ejecutamos:
NameBlock nb1 = [[ Real a = 1 ]]; NameBlock nb2 = [[ Real a = 2 ]]; NameBlock nb3 = [[ Real b = 1 ]]; NameBlock nb4 = nb1; Real (nb1 <: [[ nb2 ]]); // > False Real (nb1 <: [[ nb3 ]]); // > True Real (nb1 <: [[ nb4 ]]); // > True
se obtiene falso el primero y cierto los otros dos, cuando yo propondría cierto sólo el último (aun cuando el miembro de nb3
se llamara a
).
comment:3 Changed 14 years ago by
Status: | new → accepted |
---|
Hace poco arreglé algo parecido en el ticket #1016, pero ya lo voy a revisar.
comment:4 Changed 14 years ago by
En el ejemplo que se propone el error se porduce al comparar objetos con referencias cíclicas:
NameBlock nb1 = [[ Real a = 1, Set obj = Copy(Empty) ]]; NameBlock nb2 = [[ Real a = 1, Set obj = [[nb1]] ]]; Set nb1::obj := [[nb2]]; Real (nb1 <: [[ nb1, nb2 ]]);
El problema se solucionaría con el criterio de comparación propuesto.
comment:6 Changed 14 years ago by
Si cambiamos el comportamiento como se propone del operador entonces rompemos la compatibilidad hacia atrás.
Lo que sí se puede hacer es cortocircuitar las comparaciones de forma que si se compara un objeto consigo mismo se resuelva en empate devolviendo 0 sin más dilación. Antes de llegar al comparador de contenidos existe una función interna que toma los punteros para determinar el tipo de ambos, y es ahí donde se puede hacer esto. Aún puede quedar algún cabo suelto puesto que a veces lo que le llega ahí es el puntero de un objeto cáscara que referencia al verdadero objeto pero si nos encontramos con ese problema ya veremos cómo atacarlo.
comment:7 Changed 14 years ago by
Entiendo el problema de la compatibilidad hacia atrás.
Pero quizá no debería ser la única razón para dejar algo como está.
Según la forma de comparar actual, dos conjuntos son iguales aunque varíe el orden de sus elementos:
Real Compare([[1,2]],[[2,1]]); //-> 0
dos matrices son iguales si tienen el mismo número de filas y columnas:
Real Compare(Col(1,2),Col(3,4)); //-> 0
o dos nameblocks son iguales aun cuando no tienen nada que ver (no hemos de olvidar que los miembros de un nameblock han de tener nombres):
Real Compare( NameBlock [[Real visible = True, Real active = False ]], NameBlock [[Real visible = False, Real active = True ]] ); //-> 0
por enumerar algunas.
Al menos sí crearía una alternativa a Compare
más razonable y permitiría que fuese un argumento opcional de Unique
. Y ya que no puedo ponerle argumentos opcionales al operador <:
crearía un método Belong
con idéntico comportamiento al operador y un segundo argumento opcional.
comment:8 Changed 14 years ago by
Component: | ASCII data files → Kernel |
---|---|
Milestone: | → Mantainance |
Priority: | highest → normal |
Severity: | blocker → normal |
Aunque pueda sonar a excusa voy a dar un compendio de las razones que han llevado a un estado tan incoherente, con el único objetivo de que se entienda bien la complejidad del asunto y que se acometa esta tarea con conocimiento de causa y cuando haya los recursos necesarios.
Lo primero que hay que aclarar es qué significa comparar. El problema es que la función de comparación actual lo que pretende es crear no sólo una relación de equivalencia sino también una relación de orden pues las dos eran necesidades perentorias y no había tiempo para distingos. Así pues se aprovechó el hecho de que en los tipos escalares Real, Text, Date
, que es en los que se pensó originalemente que debían obrar estas operaciones, el actual Compare sirve para los dos objetivos, igualdad y orden, pues Compare(a,b)
devuelve -1 si a<b, 0 si a==b, 1 si a>b
Tiene sentido decir si dos matrices son iguales si tienen la misma estructura y los mismos elementos en el mismo orden interno, pero no siempre tiene sentido hablar de una matriz mayor que otra, sólo si tienen las mismas dimensiones y todos los elementos de la una son mayores que los correspondientes de la otra en la misma celda. En los tipos vectoriales Complex, Matrix, Polyn, Ration, Set, NameBlock
, no tiene sentido hablar de una relación de orden, a lo sumo puede darse una relación de orden parcial que no es válida para ordenar elementos.
Por otra parte están los objetos abstractos como las series infinitas, los conjuntos temporales o las funciones, en los que la relación de igualdad sí existe por derecho pero es de hecho no implementable sin una herramienta de cálculo simbólico que tendría un coste implanteable, por lo que simplemente se comparan los punteros sin más.
Al principio sólo existía comparación de los tipos concretos, pero poco a poco se fue solicitando ampliarla a otros tipos por los más variados motivos, pero siempre con una urgencia voraz, lo cual llevó mediante sucesivos parches al estado actual.
Para hacer bien las cosas, habría que distinguir internamente dos operadores de comparación:
- un operador
is_equal_to
para la relación de igualdad que podría darse para todos los tipos concretos y que se reduciría a comparación de punteros para los tipos abstractos. Este obraría en operaciones como==, !=, <:, Unique
. En los tipos vectoriales podría resultar lenta pero eso es problema del usuario, que no compare cosas por comparar sino sólo lo que necesita. El orden de los elementos dentro de un conjunto es irrelevante en cuanto a las propiedades del conjunto en el sentido matemático, de ahí que si un conjunto es una permutación de otro se consideren ambos iguales. Si se estima oportuno es posible crear otras funciones basadas en el criterio de comparación de igualdad vectorialReal VEQ(Set a, Set b)
y lo mismo un VUnique y un VBelong. Yo creo que eso debe seguir teniendo vigencia este tipo de relación de igualdad. El tipo NameBlock tiene internamente un Set en el que delega la comparación. En realidad tengo dudas de si tiene sentido hacer comparaciones de NameBlock más allá de igualdad de punteros, especialmente cuando es una instancia de clase, pues está casi más cerca de un compartamiento de tipo abstracto que de tipo concreto.
- un operador
compare
para la relación de orden que se daría exclusivamente para los tipos escalares. Este obraría en operaciones como<,<=,>,>=
que actualmente devuelven incoherencias varias cuando simplemente deberían dar un error.
comment:10 Changed 14 years ago by
En la versión v2.0.1 b.0.54.alpha se soluciona el problema de la caída con la que se abrió el ticket.
comment:11 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
Dejo el oza en
nas\share\personas\IRobles
El tamaño excede el máximo permitido