vb6 es tonto

Iniciado por Psyke1, 2 Octubre 2011, 01:08 AM

0 Miembros y 1 Visitante están viendo este tema.

Psyke1

Hola chicos, bueno a raíz de una discusión con la profesora de programación he investigado sobre los Ifs de vb6... :rolleyes:

En esta situación:
Código (vb) [Seleccionar]
If A = True Or B = False Then
Lo lógico sería que al leer A=True no comprobara Lo siguiente puesto que la condición se cumpliría de todas formas. :)
Pero no, vb te comprueba TODO el If pase lo que pase en todos los casos. :¬¬

Aquí un código que lo demuestra:

Código (vb) [Seleccionar]
Option Explicit

Private Function OrTest(ByVal bReturn As Boolean) As Boolean
   '// Imprimo un texto para saber que he pasado por la función.
   Debug.Print Time$, "Función con el argumento " & bReturn & " llamada."
   OrTest = bReturn
End Function

Private Sub Form_Load()
   
   '// Aquí lo logico sería comprobar las dos ya que
   '// si la primera no es true, lo puede ser la segunda.
   If OrTest(False) Or OrTest(False) Then
       '// Nothing
   End If
   
   Debug.Print String$(75, "=")
   
   '// Lo lógico sería que se saltase la segunda función puesto
   '// que la primera es true, pero no, nuestro querido vb
   '// comprueba igual...
   If OrTest(True) Or OrTest(False) Then
       '// Nothing
   End If
End Sub


Retorno:
00:27:48      Función con el argumento Falso llamada.
00:27:48      Función con el argumento Falso llamada.
===========================================================================
00:27:48      Función con el argumento Verdadero llamada.
00:27:48      Función con el argumento Falso llamada.




Sé que alguno dirá: ¿y a mí qué más me da si el resultado es el mismo?
Bueno, pues imagina que tienes un If tal que así:

Código (vb) [Seleccionar]

If Calculo(1) Or Calculo(2) Or Calculo(3) Or Calculo(4) Or Calculo(5) Then
    '...
End If

La función Calculo() es un algoritmo complejo y tarda 1 segundo de media.
Si fuera otro lenguaje de programación si Calculo(1) es true se saltaría los demás, pero nuestro querido vb6 llamará a todas las demás funciones perdiendo tiempo innecesariamente... :-\ Pasando de 1 seg a 5 en este caso.
La alternativa que propongo en estos casos es (no son agradables a la vista, aviso :xD) :

Sustituir esto:
Código (vb) [Seleccionar]

   If A(324) = 45 Or B(12) = 2 Or B(4563) = 56 Then
       Call DoIt
   End If


Por esto:
Código (vb) [Seleccionar]

   If A(324) = 45 Then
        Call DoIt
   ElseIf B(12)=2 Then
        Call DoIt
   ElseIf B(4563) = 56 Then
       Call DoIt
    End If


Esto:
Código (vb) [Seleccionar]

   If A(324) = 45 And B(12) = 2 And B(4563) = 56 Then
       '...
   End If


Por esto:
Código (vb) [Seleccionar]

   If A(324) = 45 Then
       If B(12) = 2 Then
           If B(4563) = 56 Then
               '...
           End If
       End If
  End If

Con esto no quiero decir que lo hagáis así de normal, sólo cuando necesitemos velocidad.
Hice estas pruebas a ver si algún lenguaje más era tonto, pero por ahora sólo es vb6.
Si alguien sabe de otro hacedmelo saber, me interesa mucho.
Dedico este articulo a Karcrack, BlackZero, TheSwash y raul338 por orientarme y ayudarme con los test.

VB.NET tiene una expresion para evitar esto:
Short-Circuiting Logical Operations http://msdn.microsoft.com/en-us/library/wz3k228a.aspx

Más info:
http://en.wikipedia.org/wiki/Short-circuit_evaluation

Espero que al menos a alguien le sirva todo esto. :)

DoEvents! :P

$Edu$

No sabias esto de antes? :S hasta yo lo sabia xD

En .net por ejemplo ya tienes opcion, si quieres un "Or" comun como en vb6 o un "Or" mas "rapido" que saldra si ya no cambiara en nada las siguientes condiciones con el final.

Te da para elegir porque a veces aunque la condicion final no cambiara, necesitamos que entre a una funcion que mostrara talvez un mensaje de error.

BlackZeroX

.
Es BlackZeroX... no BlackZero ¬¬"

Lo probaste compilado?...

Dulces Lunas!¡.
The Dark Shadow is my passion.

79137913

HOLA!!!

Es cierto, Pero no es noticia :S

Cuento viejo...

Pero... proba compilando en Otros modos de compilacion.

GRACIAS POR LEER!!!
"Como no se puede igualar a Dios, ya he decidido que hacer, ¡SUPERARLO!"
"La peor de las ignorancias es no saber corregirlas"

79137913                          *Shadow Scouts Team*

Psyke1

#4
Sí, probé compilado. :P
Yo también sabía esto de hace tiempo, pero ingenuo de mí, llegué a pensar que en todos los lenguajes era igual. :laugh:
Y la gente que no programa en vb6 no lo suele saber, así que no creo que esto haya sido 100% en vano.

DoEvents! :P

Yoghurt

No han escuchado por ahí o leído de que VB comprueba desde la izquierda hacia la derecha??

Por ejemplo en:
If (A=True) Or (B=False) Then ...

Comprueba si B=False y Luego si A=True. Eso lo tengo en mi memoria hace unos años que leí eso. Aunq me da flojera comprobarlo, ahora que salió el tema a la "parrilla" :)

P.D.: Siempre se ha sabido de las falencias de la Microsoft con Todos sus productos, aunq ya deberían saberlo y da risa cuando sale uno alegando por los defectos =D

$Edu$

Eso si q no xD, lee de izquierda a derecha es decir primero A y luego B, y esto que se habla aca no son "defectos" sino que no tiene la capacidad de elegir cuando usar And comun y cuando no, en cambio vb.net si lo tiene.

Con este codigo se van todas las dudas.

Código (vb) [Seleccionar]

Private Sub Form_Load()
If (EnLinea("Nestor")) And (EnLinea("edu")) Then
MsgBox "Imposible que aparezca este mensaje!"
End If
End Sub

Private Function EnLinea(ByVal contacto As String) As Boolean

If contacto = "edu" Then
    MsgBox "Edu siempre esta online xD" ' entonces da true
Else
    MsgBox "No esta conectado!"
    Exit Function
End If

EnLinea = True

End Function

Sanlegas

#7
Me imagino que ha de comprobar las demas condiciones por si hay otro operador logico que pueda comprobar, como un XOR, ejemplo:

Código (vb) [Seleccionar]
Option Explicit

Private Function OrTest(ByVal bReturn As Boolean) As Boolean
   '// Imprimo un texto para saber que he pasado por la función.
   Debug.Print Time$, "Función con el argumento " & bReturn & " llamada."
   OrTest = bReturn
End Function

Private Sub Form_Load()

   '// Aquí lo logico sería comprobar las dos ya que
   '// si la primera no es true, lo puede ser la segunda.
   If OrTest(False) Or OrTest(False) Then
       '// Nothing
   End If

   Debug.Print String$(75, "=")

   If OrTest(True) Or OrTest(False) Xor OrTest(True) Then
       Debug.Print "OK!"
       '// Nothing
   End If
End Sub


Como dicen ustedes con la primera comparación tendria que salirse e imprimir "OK!", pero como el XOR da false no lo imprime, salu2 !

seba123neo

Cita de: $Edu$ en  2 Octubre 2011, 01:18 AM
No sabias esto de antes? :S hasta yo lo sabia xD

En .net por ejemplo ya tienes opcion, si quieres un "Or" comun como en vb6 o un "Or" mas "rapido" que saldra si ya no cambiara en nada las siguientes condiciones con el final.

AndAlso y OrElse en .NET son operaciones cortocircuitadas, asi como el operador ternario de java "?"
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

$Edu$

Gracias seba, y Tenient.. el mensaje "OK!" saldra SOLAMENTE si el la condicion es verdadera, y como dices es falsa entonces obvio que no entra, lo que estamos diciendo es que sea True o False la condicion, pasara uno por uno, en este caso tiene que mirar todos obligado por el xor que pusiste pero deciamos en caso como if true or true or true or true or true or true or true..., con el primero ya da True la condicion y no necesitaria comprobar todos los otros, pero si lo hace, pero en .net como dice seba existe el OrElse que no va a verificar el resto de las condiciones ya que no cambiaran el resultado.