UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA DEPARTAMENTO DE INFORMÁTICA TEÓRICA INF05516 – SEMÂNTICA FORMAL N – 2006/1 Bárbara Bellaver – 000XXXXX Virginia Papeé de Oliveira - 00026831 Professor : Marcus Ritt Nomes : Turma: A Data : 20/11/2006 Trabalho Final – Resumo de Artigo Structured Programming with go to Statements Donald E. Knuth Introdução O presente trabalho tem como objetivo resumir as principais idéias levantadas por Donald E. Knuth, da Stanford University, sobre a utilização do comando go to na programação estruturada. Essas idéias fazem parte do seu artigo intitulado “Structured Programming with go to Statements”, publicado em dezembro de 1974 na Computing Surveys, onde o autor traz à tona pontos de vista opostos sobre os comandos go to e questiona se este tipo de comando deveria ser abolido ou não. Todo o artigo é escrito em primeira pessoa para, segundo o próprio autor, enfatizar o fato de que o que ele está dizendo é apenas a opinião de um homem e que ele não espera convencer ninguém de que suas considerações estão corretas. O autor defende a eliminação dos go to’s em certos casos, e a introdução deles em outros casos. Ao longo do artigo Knuth tenta construir um estudo abrangente sobre a controvérsia do go to, discutindo prós e contras, mas sem adotar um posicionamento forte até que a discussão esteja completa. Para isso autor apresenta diversos exemplos de programas, alguns dos quais negando as conclusões de exemplos anteriores. O artigo, num total de 41 páginas, pode ser dividido em três grandes partes : 1. Eliminação dos comandos go to; 2. Introdução dos comandos go to; e 3. Conclusões. A seguir são apresentadas as principais idéias abordadas em cada uma delas . Structured Programming with go to Statements - 1 - Eliminação dos comandos go to Background Histórico Para Knuth a discussão sobre a abolição dos comandos go to teve início na década de 60 quando diversos programadores passaram a publicar artigos condenando o uso deste comando. Segundo eles a eliminação de go to’s tornava um programa mais fácil de entender, depurar, modificar e incorporar em programas maiores. O resultado seria um código mais curto e mais claro. Em 1968 Dijkstra submeteu um pequeno artigo à Communications of the ACM devotado inteiramente à discussão dos comados go to cujo título era “Go to statement considered harmful”. Djikstra expressava sua convicção de que go to’s deveriam ser abolidos de todas as linguagens de programação de alto nível pois o comando era muito primitivo, sendo um convite a fazer bagunça dentro de um programa. Ele encorajava que construções alternativas fossem propostas .O artigo rapidamente se tornou conhecido e desde então aumentaram os sentimentos contrários aos comandos go to. Em 1971 Knuth e seu colega Floyd publicaram o artigo “Notes on avoiding go to Statements” . Ambos descobriram que não havia maneira de implementar certas tarefas simples usando comandos while e condicionais substituindo go to’s a menos que computação extra fosse especificada. Eliminando go to’s G. Jacopini provou em 1966, em um artigo escrito conjuntamente com C. Böhm, que qualquer programa dado, por exemplo na forma de um diagrama de fluxo (flowchart), pode ser sistematicamente transformado em outro programa, o qual computa os mesmos resultados do original, usando apenas as três operações básicas de composição, condicional e iteração, mais os possíveis comandos de atribuição e testes sobre as variáveis auxiliares. Portanto, a princípio, comandos go to, podem sempre ser removidos. Mais tarde, Cooper em 1967 e Bruno e Steiglitz em 1972 afirmaram que de um ponto de vista prático o teorema de Jacopini era sem significado, pois na realidade qualquer programa pode obviamente ser colocado em uma forma “belamente estruturada”. p :=1; while p>0 do begin if p=1 then perform step1; p := successor of step 1 fi; if p=2 then perform step2; p := successor of step 2 fi; … if p=n then perform step n; p := successor of step n fi; end. A variável auxiliar p serve como um contador de programa representando em qual caixa do diagrama de fluxo se está, e o programa pára quando p se torna zero. Todos os go to’s foram eliminados , mas na realidade toda a estrutura do programa foi perdida. Structured Programming with go to Statements - 2 - A construção original de Jacopini não era meramente a emulação trivial de um fluxograma indicada acima. Seria possível aproveitar muito da estrutura de um fluxograma dado se ele fosse razoavelmente bem comportado. Ashcroft e Manna em 1972 criaram outra técnica para a eliminação de go to’s , tornando possível capturar ainda mais do fluxo natural de um programa. Por exemplo, dado o algoritmo original abaixo à esquerda, obtém-se o algoritmo equivalente à direita. compare: if A[i] < x then if L[i] ≠ 0 then i := L[i]; go to compare; else L[i] := j; go to insert fi; else if R[i] ≠ 0 then i := R[i]; go to compare; else R[i] := j; go to insert fi; fi; insert: A[j] := x; L[j] := 0; R[j] := 0; j := j+l; t := true; while t do begin if A[i] < x then if L[i] ≠ 0 then i := L[i]; else L[i] := j; t := false fi; else if R[i] ≠ 0 then i := R[i]; else R[i] := j; t := false fi; end; A[j] := x; Este algoritmo é parte do bem conhecido problema de pesquisa e inserção em árvore, onde uma árvore binária de pesquisa é representada por três vetores : A[i] denota a informação armazenada no nodo número i, e L[i], R[i] são os respectivos números de nodo para as raízes das subárvores esquerda e direita do nodo. Árvores vazias são representadas por zero. O programa pesquisa a árvore de cima para baixo até encontrar uma subárvore vazia onde x possa ser inserido; e a variável j aponta o lugar apropriado para fazer a inserção. De forma geral a técnica de eliminação de go to’s de Ashcroft e Manna pode fazer um programa crescer exponencialmente em tamanho, e quando saídas de erro ou outros go to’s reentrantes estão presentes, os programas resultantes irão na realidade parecer como o emulador de fluxograma acima. Quando procedimentos de eliminação de go to são aplicados a programas mal estruturados, pode-se esperar como resultado programas igualmente mal esruturados. Em outras palavras, segundo Knuth, nós não deveríamos remover comandos go to simplesmente porque está na moda fazer isso, a presença ou ausência de comandos go to não é realmente o importante. A estrutura do programa é o que conta. Provavelmente o pior erro que alguém pode cometer com respeito ao assunto de comandos go to é assumir que “programação estruturada” é alcançada escrevendo-se programas da forma como sempre e então eliminando os go to’s. Muitos dos go to’s não deveriam nem existir em primeiro lugar! O que se deseja é que programas sejam concebidos de tal forma que raramente sequer se pense sobre os comandos go to porque a real necessidade deles dificilmente aparece. A linguagem na qual expressamos nossas idéias tem forte influência sobre nossos processos de pensamento. Por isso Dijkstra salienta a necessidade de novas instruções (features) em linguagens de programação - estruturas que encorajam o pensamento clarocom o objetivo de evitar a tentação do go to. Structured Programming with go to Statements - 3 - Indicadores de Evento Segundo Knuth a melhor instrução (feature) que ele conhecia para evitar o uso dos comandos go to havia sido recentemente proposta em um artigo de C.T.Zahn , consistindo de um indicador de evento a ser introduzido nas linguagens de programação. Este constructo dirigido a evento poderia ser escrito de duas formas : A) loop until event1 or … or eventn: statement list0; repeat; then event1 = > statement list1; … eventn = > statement listn; fi; B) begin until event1 or . . . or eventn: statement list0; end; then event1 = > statement list1; … eventn = > statement listn; fi: Reescrevendo o problema de pesquisa e inserção em árvore binária segundo essa nova feature obtém-se o código abaixo : loop until left leaf hit or right leaf hit: if A[i] < x then if L[i] ≠ 0 then i := L[i]; else left leaf hit fi; else if R[i] ≠ 0 then i := R[i]; else right leaf hit fi; fi; repeat; then left leaf hit = > L[i] := j; right leaf hit = > R[i] := j; fi; A[j] := x; L[j] := 0; R[j] := 0; j := j+l; A primeira linha do constructo simplesmente declara os nomes dos indicadores de evento. Indicadores de evento não são condições que são testadas continuamente. Os comandos event são simplesmente transferências de controle que podem ser tratadas eficientemente pelo compilador. Então, no exemplo acima, o comando “leaf replaced”é essencialmente um go to que pula para fora do laço. Iterações Simples Segundo Knuth os comandos de iteração mais freqüentemente propostos como alternativas aos comandos go to têm sido "while B do S" e "repeat S until B". E as iterações que ele encontra mais freqüentemente têm a forma A: S; if B then go to Z fi; T; go to A; Z: Onde S e T ambos representam longas seqüências de código. Se S é vazio, tem-se um laço while, e se T é vazio tem-se um laço repeat (Djikstra chamou este tipo de laço como um laço que é executado “n and a half times”). Structured Programming with go to Statements - 4 - A prática usual para evitar go to’s em tais laços consiste de : 1. duplicar o código para S escrevendo S; while B do begin T; S end; 2. ou descobrir algum tipo de “inversa”para T de tal forma que “T-1;T” é equivalente a um comando nulo e escrever T-l; repeat T; S until B; 3. ou duplicar o código para B e fazer um teste redundante, escrevendo repeat S; if B then T fi; until B; Para Knuth a primeira real solução de sintaxe para o problema do laço n+1/2 foi proposta por Ole Johan Dahl, que sugeria escrever a iteração simples proposta acima como loop; S; while B: T; repeat; Uma das propriedades interessantes desta sintaxe é que a palavra repeat ocorre naturalmente ao final de um laço, e não no começo. Assim, quando se chega ao final, se é instruído a repetir o loop, ao invés de ser informado que o texto do laço (e não sua execução) terminou. Também é interessante o fato que a proposta de Dahl funciona também quando S ou T é vazio, e então tem-se uma sintaxe iniforme para todos os três casos. Assim, loop while B: T; repeat; toma o lugar de “ while B do begin T end;” e loop: S while B repeat; toma o lugar de "repeat S until B;". Structured Programming with go to Statements - 5 - Conclusão Structured Programming with go to Statements - 6 -