2008/12/09


Exemplo de laço complicado

Eu sou um defensor da instrução GOTO, acho que as pessoas devem pelo menos aprender como funciona quando tão na escola. Já escrevi muito por aqui a respeito do GOTO, e do preconceito sem noção, etc.

Tudo bem que dá pra resolver qualquer problema com os for e whiles da vida, e os breaks e continues auxiliam, mas não deixa de ficar feio né gente... Não sei se fica menos feio do que usar um GOTO.

Olha esse exemplo aqui de código real que tem um laço complicado. Achei interessante porque vem direto de uma documentação de uma biblioteca, é um programa bem básico, é muito pequeno, e tem um laço bizarro.




lexer = lex.lex()
lexer.input(sometext)
while 1:
tok = lexer.token()
if not tok: break
print tok

Olha só, o sujeito teve que fazer um laço “infinito”, algo sempre chamativo. Aí tem uma atribuição, um teste com break, e um print. O problema é que não dá pra testar o tok de cara, porque é preciso a primeira atribuição. nao dá pra fazer do ... while também porque o print precisa ficar depois do teste. Não tem jeito. O teste teve que ficar no meio desses dois. Aí então faz um “laço infinito com break no meio”. Uma estrutura que não tem nome. Se fosse GOTO, seria simplesmente mais um “laço com um teste”... Pra entender esse programa eu uso mais meus conhecimentos de programação fudamental, sabedora do GOTO, do que as facilidades estruturantes oferecidas pelas estruturas whiles e fors da vida.

Claro que dá pra fazer um jeito do programa ficar mais bonito, e o verdadeiro teste que limita o laço ficar na declaração do while. Tipo:




lexer = lex.lex()
lexer.input(sometext)
tok = lexer.token()
while tok:
print tok
tok = lexer.token()

Deve até poder ficar melhor com for. Mas algo levou esse programador a optar por uma única linha de atribuição, e um break, achou que talvez isso fosse mais claro, mais simples, mais de acordo com as famosas “limitações de suas habilidades cognitivas” que preocupavam Dijkstra. Eu pergunto: Será que estamos satisfeitos com nossas linguagens?...

3 comments:

nf said...

Eu também sempre achei feio loops infinitos! No C isso ficaria mais bonito:

while (tok = lexer.token())
{
    print tok;
}

Mas no caso do Python, isso é claramente um erro na biblioteca. O Python não precisa de "while 1". O ideal seria que a interface dessa biblioteca disponibilizasse um iterator do tipo:

for tok in lexer.tokens:
    print tok

Anonymous said...

Uai! Mas eu aprendi GOTO na escola, e hoje, quinze anos depois, nunca mais precisei usar...

:(

Nicolau said...

NF: Poisé, o FOR matava a pau. Eu ia falar dessa possibilidade, mas aí li que teria que ser uma lista, o que não é o caso... Não tou por dentro desse lance de iterators, e imagino que certamente seria o caso. Vc tem um ponteiro pra nós? :]

Lia: Bom, tenho certeza que tem muitas outras coisas que, assim como o GOTO, são fundamentais, que vc aprendeu na escola, mas nunca mais precisou usar!!... Não prego o uso do goto em "produção", apenas acho que tem que ser ensinado, e não escondido das gerações mais novas como se fosse fazer bem para o aprendizado deles nem saber que isso existe. Não faz. Mas tem que saber A Verdade...

Laço infinito com break no meio pra mim parece algo muito distante do que os inventores dos laços tipo while e for tinham e mente. Só pensando em um bloco com um desvio incondicional e um desvio condicional no meio é que eu entendo direito um programa desses...