Re: [pyar] ¿If anidado?

Página superior
Adjuntos:
+ (text/plain)

Responder a este mensaje
Autor: Gabriel Genellina
Fecha:  
A: pyar
Asunto: Re: [pyar] ¿If anidado?
En Fri, 18 Sep 2009 02:57:18 -0300, Claudio Freire
<klaussfreire@???> escribió:
> 2009/9/18 Gabriel Genellina
> <gagsl-py2@???>
>
>> Epa, no es para tanto, y más si sólo nos restringimos a la variante de
>> break y continue que existe en Python (sólo se puede salir o continuar
>> el
>> bucle más anidado). Acá [1] se presenta una formalización de la
>> semántica
>> del while con break/continue/return y excepciones para Java, pero se
>> aplica
>> igual a Python (tanto como se pueda aplicar una teoria originalmente
>> pensada
>> para lenguajes mucho mas restrictivos y simples...)
>>
>
> Ciertamente casos particulares tienen formalizaciones, y esta que vos
> citás
> es una para el caso en cuestión.
> Pero...
>>
> Un bucle complejo ya es difícil de analizar (ej: analizá el bucle
> principal
> del camino mínimo de dijkstra). Ahora agregale un par de breaks y
> continue.
> Vas a ver que demostrar que el invariante se mantiene entre ciclos se te
> hace muchísimo más arduo, porque cada break y cada continue te crea un
> caso
> particular para analizar por separado.
>
> Formalmente, uno se toma el trabajo - no es taaan dramático.
>
> Informalmente, destruye la intuición - drama y lágrimas.
>
> Lo que antes era intuitivo:
>
> while not edad.isdigit():
> #20 líneas de código para hacer I/O
>
> Se convierte en poco intuitivo
>
> while True:
> #10 líneas de I/O
> if not edad:
> continue
> # 5 líneas de conversión de datos
> if edad.isdigit():
> break
> # 5 líneas de fruta
>
> (sí, compliqué un poco el while ;) )


(y cambiaste el significado, porque no veo que ambos casos sean iguales)

> Esto ya no es intuitivo. Uno tiene que inspeccionar (y con cuidado) el
> cuerpo del bucle para saber qué se cumple a su salida. En la versión
> anterior, no me importaba realmente el cuerpo, yo *sabía* que si sale del
> bucle entonces "edad.isdigit()" por la primera línea.


Es complicado razonar sobre ese bucle porque el codigo es complicado, no
porque use break/continue. Podes convertirlo en un bucle "normal" con la
condicion al principio:

#10 líneas de I/O
while not edad:
#10 líneas de I/O
# 5 líneas de conversión de datos
while not edad.isdigit():
# 5 líneas de fruta
#10 líneas de I/O
while not edad:
#10 líneas de I/O
# 5 líneas de conversión de datos

Si no meti la pata, esa es la estructura equivalente. Pero sinceramente no
me parece mas simple :)
Claro, mirando la condicion del 'while' puedo decir de un vistazo que si
sale del bucle, edad.isdigit() es verdadero. Y tambien puedo hacer lo
mismo con el otro codigo, solo que tengo que mirar en otro lado (el 'if'
que precede al break).

> El gran problema, entonces, es la pérdida de la intuición como
> herramienta.
> Por eso los profesores de programación prohiben su uso, y cualquier libro
> simplemente lo desalienta. Porque, si tenés una manera *sencilla* que
> evite
> breaks y continues, en general es preferible.
>
> Básicamente, uno tiene que mirar ambas opciones y pensar ¿vale la pena
> este
> break?
> Así de simple.


Claro, igual que todo, se puede abusar. Pero hay algunas construcciones
comunes que son cómodas, y tan fácil de razonar sobre ellas como la
versión sin break/continue. Por ejemplo:

while True:
S1
if C:
break
S2

es una estructura común, que hasta podría haber tenido su propia sintaxis.
Es nada mas que un bucle con la condicion en el medio, y se puede
transformar (formalmente) en un bucle con la condición al principio:

S1
while C:
S2
S1

y si demostras que este bucle es correcto y termina, tambien el otro. Es
decir, no es más dificil razonar sobre el primero que sobre el segundo,
pero el primero tiene algunas ventajas (como que S1 no está repetido, y
puede ser algo grande, como en tu ejemplo de arriba).

Y la intuicion tambien funciona: una vez que aprendes a reconocer esa
estructura ("bucle con condicion en el medio"), decir cuál es la
postcondicion a la salida es trivial: es la del 'if' que tiene el break.

Hay otras construcciones básicas que son reconocibles a simple vista:

for item in container:
if not condition: continue
S

Para mi, eso refleja mejor la estructura del codigo que si lo hubiera
escrito de esta forma:

for item in container:
if condition:
S

y demostrar la correccion de uno u otro es exactamente lo mismo: el
'continue' no molesta, realmente.

De vuelta, lo importante es no abusar. Codigo inentendible e indemostrable
se puede escribir con y sin sentencias de terminacion abrupta. A mi me
parece que restringir artificialmente el lenguaje sólo porque ciertas
construcciones no fueron consideradas por un formalismo diseñado en los
'70 no tiene mucho sentido. Si vamos al caso, en Python ni siquiera las
reglas mas basicas se cumplen siempre; se puede escribir un programa donde
esto no sea cierto:

{ b==0 }
a=b
{ a==0 }

y ni hablemos si en lugar de nombres simples tenés objetos involucrados.

-- 
Gabriel Genellina



---------------------------------------------------------------------
Para dar de baja la suscripcion, mande un mensaje a:
   pyar-unsubscribe@???


Para obtener el resto de direcciones-comando, mande un mensaje a:
pyar-help@???

PyAr - Python Argentina - Sitio web: http://www.python.com.ar/