Pienso-Pienso: Cual es la salida de este programa?
(ejemplo brindado por Alejandro Rinaldi).
Tengo dos tablas:
CasaId | PersonaId | Color |
PEPE01 | MUJICA | NEGRO |
CUQUI01 | LACALLE | BLANCO |
CUQUI02 | LACALLE | VERDE |
Autos
AutoId | PersonaId | Color |
PEPE10 | MUJICA | BLANCO |
PEPE11 | MUJICA | NEGRO |
CUQUI10 | LACALLE | NEGRO |
También existen una tabla de colores y de personas, pero no son relevantes para el problema.
Necesito hacer un programa que liste las casas, con sus dueños e indique si hay autos con el mismo color, no importado que los autos sean de la misma persona que la casa.
Para esto hago un procedimiento (main, command line, en C#) que hace
for each CasaId&Color=Colordo 'BuscoAutosDelMismoColor'Msg(format('Casa %1 de %2 es color %3. Hay autos del mismo color %4 ',CasaId,PersonaId,Color,&HayAutosDelMismoColor),status)endforSub 'BuscoAutosDelMismoColor'&HayAutosDelMismoColor='N'for each AutoIdwhere Color=&Colordefined by AutoId,PersonaId,Color&HayAutosDelMismoColor='S'endforendsub
Cuando ejecuto el programa, cual es la salida del mismo? Justifique su respuesta
1)
Casa CUQUI01 de LACALLE es color BLANCO . Hay autos del mismo color S
Casa CUQUI02 de LACALLE es color VERDE . Hay autos del mismo color N
Casa PEPE01 de MUJICA es color NEGRO . Hay autos del mismo color S
2)
Casa CUQUI01 de MUJICA es color BLANCO . Hay autos del mismo color S
Casa CUQUI02 de LACALLE es color VERDE . Hay autos del mismo color N
Casa PEPE01 de MUJICA es color NEGRO . Hay autos del mismo color S
3)
Casa CUQUI01 de LACALLE es color BLANCO . Hay autos del mismo color SCasa CUQUI02 de LACALLE es color VERDE . Hay autos del mismo color S
Casa PEPE01 de MUJICA es color NEGRO . Hay autos del mismo color S
El programa tiene como salida la 2).
El problema es que la subrutina "pasa por arriba" el valor de PersonaId, y el valor que se traia en el primer for each, son sobreescritos por los traidos en la subrutina.
Una solucion, es sacar el defined by de la subrutina, y ahi si la respuesta sera la correcta (la 1))
yo se maestra! yo se maestra!!
ResponderBorrarSi fuera por el lado de "como debe ser" según el código me voy por la 1, pero siento que hay trampa en el pienso pienso.
ResponderBorrarJustificarlo? el único que tiene una casa verde es Lacalle y no existen autos verdes.
Yo le agregaría al for each de busco un exit cuando encuentra un auto del mismo color, solo para que sea mas eficiente.
hay trampa?
Voy por la dos porque por ahí Gx se tara y se queda con la persona de la subrutina, pido perdón si es un disparate pero hace como 1 anio y medio que no toco gx.
ResponderBorrarñ... al fin la encontré pero ya había mandado el comentario :)
ResponderBorrarUna SubRutina y un procedimiento Externo (call) deberían dar los mismos resultados, por lo que si difieren el uno del otro es ERROR de GX.
ResponderBorrarDebería ser el 1.
Si difiere el resultado por usar subrutina? Cuando debemos usarlas? para algo "simple"? o hacemos prueba y error?
David:
ResponderBorrarEs un programa GeneXus y no es intutivo. No se si llamarlo tramposo.
Andres:
Siempres sirve el ALT-164 para la minuscula y 165 para la mayuscula. Tu respuesta es correcta.
Anonimo:
ResponderBorrarConcuerdo que es confuso. No se si llamarlo error, porque no segun las especificaciones las variables son globales. Pero que recorrer otra tabla, modifique el resultado de lo que traje en otra recorrida, es muy confuso y produce errores dificiles de detectar.
Por ejemplo, si en mi codigo saco el defined by (que a los efectos del codigo no agrega nada) la salida es la 1).
Seria bueno encontrarle una solucion, pero creo que no debe ser facil.
Tener subrutinas con parametros y variables de alcance limitado solo dentro de ellas, puede ayudar mucho a ahorrarnos estos dolores de cabeza.
Gracias por el comentario.
La verdad que el uso de subrutinas, cuando se "corta" una recorrida (como el caso del ejemplo), nos ha traído más de un dolor de cabeza.
ResponderBorrarMuchas veces cuando un programa no hace lo que debería, mi primer consejo al que me lo presenta es hacer un call a un procedimiento y no usar la subrutina.
Es muy complejo ponerse a analizar porqué funciona "mal", o "distinto" que en un call, pero si quiero seguridad siempre hago un call y me ahorro dolores de cabeza.
Y ni que hablar si viene de una migración de versiones anteriores. (por los problemas que hemos tenido, no se comportan 100% igual)
Nos ha pasado que nos cambia los valores de la recorrida principal ... el porqué no lo sé, es más fácil hacer un call que analizarlo !!! ;.)
jaja, yo ya conocia el "bug", pero me hice el choto.
ResponderBorrarEste bug fue reportado ya en las primeras versiones del generador C#, fue reportado muchas veces (tengo idea de ver este tema en el foro), e inclusive ya fue un tema de un viejo pienso pienso de Marcos Crispiono similar a este caso: http://blog.marcoscrispino.com/2008/07/pienso-pienso-subrutina-que-recorre-la.html
Este problema si no mal recuerdo no se da con otros lenguajes, pero tendria que verificarse.
La verdad que por mi lado estoy estancado en las versiones de GX, tenia en mente que este problemas estaban solucionado en las versiones actuales. Hicieron la prueba en la evo 1/2 ?
Habria que reportarlo nuevamente si no fue solucionado, desde mi punto de vista no es el comportamiento correcto el que una subrutina pise el valor de los atributos del for each padre.