Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #58 da revista programar. Faz já o download aqui!

thoga31

Ed40 - opinião acerca do artigo "Lua - linguagem de programação - parte 11", de Augusto Manzano

Mensagens Recomendadas

thoga31    594
thoga31

Boa tarde.

Em tempos e meios oportunos já tive a oportunidade de felicitar por mais uma edição da Revista. Contudo, nunca tive o devido tempo de a ler com a profundidade e atenção que queria até hoje.

Decidi ler artigos numa ordem aleatória, como é costume, e parei no de Lua, do autor Augusto Manzano. Fiquei com uma expectativa positiva pois já tive a oportunidade de dar uma leitura na diagonal às outras 10 partes, tendo concluído que seria um conjunto de artigos de qualidade com os quais me poderia introduzir a esta LP no futuro.

Portanto, qual não foi o meu espanto quando me deparo com um artigo que não correspondia em nada às minhas expectativas.

Fiquei surpreso pela ligeireza que os assuntos tratados mereceram, e logo um assunto como a utilização do comando goto.

É minha opinião que o autor formulou um discurso inicial correcto e um exemplo teórico válido acerca da utilização deste comando. Contudo, o exemplo prático é exactamente o oposto do que está no texto, e dá uma ideia errónea de que a utilização exemplificada do goto é apropriada. Passo a citar:

-- inicio do programa VAIPARA
  I = 1
  ::PontoRetorno::
  print(string.format("%2d", I))
  if (I < 10) then
     I = I + 1
     goto PontoRetorno
  end
-- fim do programa VAIPARA

Note ao executar o programa que enquanto o contador da variável I for menor que 10 será apresentado seu valor. No momento em que a condição se tornar verdadeira o laço será executado. Perceba que a condição pode ser posiciona-da em qualquer parte do bloco que se deseja executar simu-lando desta maneira um laço condicional seletivo. Eis aqui uma aplicação adequada para o comando goto.

Foi precisamente para evitar este género de programação, que resulta em código esparguete, que foram formulados, criados e adoptados os ciclos comuns que conhecemos actualmente. O exemplo teórico muito bem indicado é o seguinte:

Seu uso pode ser útil em algumas situações co-mo, por exemplo, a possibilidade de se fazer o encerramento da execução de uma estrutura condicional ou de laço sem passar por todos os aninhamentos de finalização

Depois de ter dito que...

Aqueles que são contra o uso de goto em linguagens de programação alegam que seu uso pode desestruturar um programa. O que de fato é verdade.

... o exemplo prático apresentado é, a meu ver, totalmente inadequado, indo de encontro precisamente ao estilo de programação que desestrutura um programa.

Portanto, quando o autor conclui que...

Neste artigo foi apresentado o uso do comando goto inseri-do na linguagem Lua a partir de uma postura que justifica sua existência a despeito das críticas que este tipo de comando recebe de diversos profissionais da área de desen-volvimento de software.

...penso que não está a fazer uma conclusão coerente com o artigo, quando não apresentou este comando da forma correcta.

Mais, penso que a apresentação inicial do ciclo loop-exit-end carece de clareza. Poderá dar a ideia de que só Lua e outras duas linguagens (BASIC e Ada) têm a capacidade de interromper um ciclo a meio conforme uma determinada condição:

O laço loop … exit … end é uma estrutura que permite a definição e colocação da condição de encerramento do laço em qualquer parte do bloco de execução. Este tipo de laço é encontrado nas linguagens de programação BASIC e ADA, mas inexistente em outras linguagens.

O autor poderia querer referir-se apenas à questão da sintaxe e construção desta estrutura, mas a verdade é que as mais variadas linguagens possuem, no geral, formas de fazer precisamente isto. Podem não ter uma estrutura tão "limpa" como um simples loop-end, mas é perfeitamente simulável de formas igualmente simples. Por exemplo, em Pascal, linguagem minha conhecida:

while True do begin
  // comandos 1
  if ({condição de saída}) then break;
  // comandos 2
end;

Ou em Python:

while True:
  # comandos1
  if CS:  # sendo CS a condição de saída
     break
  # comandos2

Portanto, a não ser que tenha entendido muito mal o texto, creio que a ideia transmitida não é a mais apropriada e correcta, ou a desejada pelo autor.

Concluo, por fim, a minha opinião afirmando que este artigo deixou-me muito a desejar. Não só pelo facto de ter sido feita uma apresentação leviana deste comando, como também pelo facto de ter abordado temas muito díspares, sem um nível de profundidade desejável, e sem uma lógica concreta que justificasse a sua co-existência. O artigo foi, no seu geral e a meu ver, de qualidade inferior aos demais publicados anteriormente.

Endereço os meus votos de confiança ao autor em como conseguirá recuperar celeremente a qualidade dos seus artigos de Lua, esperando que compreenda, por fim, a minha opinião. Já mostrou que tem conhecimentos vastos e uma boa capacidade de comunicação de conhecimentos de forma concreta e concisa, pelo que creio que é justo afirmar que este artigo terá sido apenas o produto de um momento de "inspiração mergulhada em névoa" que qualquer um de nós poderá sofrer. Ainda assim, nestes momentos podemos cometer erros e/ou receber críticas com os quais podemos e devemos aprender, compreendendo a outra parte. :)

Cumprimentos,

thoga31.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
apocsantos    211
apocsantos

Bom dia @thoga31,

Penso que melhor que ninguém o autor poderá responder a isto.

Eu não faço do "goto" cavalho de batalha, alias não gosto de ver goto, como não gosto de ver "go sub" e coisas semelhantes, porque dão origem a "spagetti code", mas reconheço que em determinadas linguagens e tendo em conta algumas limitações, seja "propenso" o uso do GOTO.

Pessoalmente prefiro outras formas de fazer ciclos, mas compreendo que em LUA nem tudo seja "tão linear".

Cordiais cumprimentos,

Apocsantos

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Augusto Manzano    0
Augusto Manzano

Olá, apocsantos.

Sou o autor do artigo. Não quero parecer deselegante, arrogante ou que estou na defensiva, mas para responder a sua pergunta sou obrigado a relacionar as linguagens de programação que conheço ao longo de 30 anos de programação: BASIC (clássico e estruturado), FORTRAN, Ada, COMAL, Pascal, C, C++, Assembly (8086), Logo, C#, Lua, (X)HTML, Javascript, VBA, além de algumas variações de SQL. Sou professor na área de programação e atuo nesta lida a 25 anos.

A linguagem Lua em sua versão 5.2 adotou o incremento do comando "goto", o qual foi muito criticado. Pois a questão foi por qual motivo a colocação deste comando? Considerado por muito um sacrilégio de programação.

O artigo - parte 11 - da linguagem Lua demonstra o uso do comando "goto" e o justifica seu uso na criação de laços seletivos. É disso que trata o artigo: laço seletivo. Que só é encontrado de forma explicita nas linguagens BASIC (estruturado) e Ada.

Quando falamos em laços para repetição temos que considerar a existência de seis formas de laço, sendo dividido nas categorias: condicional e incondicional.

Laço incondicional só há um o PARA (for). No entanto a categoria condicional possui 5 laços, sendo 2 do tipo pré-teste (um com fluxo operacional quando condição verdadeira e outro quando condição falsa), 2 do tipo pós-teste (um com fluxo operacional quando condição verdadeira e outro quando condição falsa) e o laço seletivo.

A linguagem BASIC (estruturada) encontrada, por exemplo, nos ambientes Quick BASIC e Visual BASIC é a única do grupo que conheço que possui todos os laços. A linguagem Ada possui apenas o laço condicional (for) e o laço seletivo (tipo loop end_loop).

O laço seletivo é uma estrutura dinâmica onde posso selecionar o ponto de saída do laço. Poço selecionar se o a condição de saída será pré-teste ou pós-teste ou mesmo colocar em uma posição central do laço para interrompê-lo. Do ponto de vista prático de programação é a melhor forma de laço. E foi este tipo de laço que o artigo trata. Não se trata de fazer código "espaguete" como mencionado.

Usar uma decisão com "exit" ou "break" para interromper um laço pré-teste ou pós-teste não é uma boa prática de programação. A não ser para algumas poucas situações específicas de uma ou outra linguagem, como o exemplo seguinte em C++:

#include <iostream>

using namespace std;

int main(void)

{

float N;

do

{

cout << "Entre um valor numerico: ";

cin >> N;

if (cin.fail())

{

cout << "Erro - entre apenas valor numerico!" << endl;

cin.clear();

cin.ignore(10000,'\n');

}

else

{

break;

}

}

while (true);

cout << "Resultado = " << N + 5 << endl;

return 0;

}

A finalidade do artigo foi orientar como construir um laço seletivo, não encontrado na maior parte das linguagens de programação, em uma linguagem que não o possui utilizando-se o comando "goto".

É pertinente ressaltar que a finalidade da existência do comando "goto" em linguagens estruturadas e orientada a objetos é de permitir a construção de mecanismos lógicos que essas categorias de linguagens não dão suporte. É atender características funcionais da arquitetura funcional dos computadores.

Qual seria a razão de deixar um comando como esse? Será que os desenvolvedores de linguagens são tão ingênuos ou incautos a ponto de deixar um comando sem necessidade?

Para maiores esclarecimentos sobre laços pode-se consultar o livro:

Concepts of Programming Languages

Robert W. Sebesta

Espero ter respondido a contendo seu questionamento.

Peço desculpas pelo endereçamento do nome. Onde está escrito apocsantos considera-se thoga31.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Caro Augusto Manzano.

Já faz tempo desde que dei a conhecer a minha opinião, e fico agradado por constatar que foi ouvida.

Volto a referir que a teoria está toda muito bem apresentada no artigo, tal como foi novamente apresentada na sua mensagem. O que eu questiono mais é o exemplo prático utilizado, dizendo que é "uma aplicação adequada para o comando goto". Eu discordo que aquele seja um bom exemplo prático.

Friso mais uma vez: a teoria está toda correcta. O que coloco em causa é o exemplo prático escolhido. A meu ver, é um mau exemplo de demonstração. Aquele uso é uma má prática, muito pior prática do que qualquer break e continue.

Portanto, eu concordo que "Neste artigo foi apresentado o uso do comando goto inserido na linguagem Lua a partir de uma postura que justifica sua existência" em teoria mas não na prática.

Usar uma decisão com "exit" ou "break" para interromper um laço pré-teste ou pós-teste não é uma boa prática de programação. A não ser para algumas poucas situações específicas de uma ou outra linguagem

Considera que o uso de um goto, numa linguagem com ciclos, a fim de implementar aquilo que seria um ciclo for, é melhor prática de programação do que o uso de um break em situações que o exigem, tais como ciclos de dimensões maiores e passíveis de ter mais do que uma condição de saída?

O laço seletivo é uma estrutura dinâmica onde posso selecionar o ponto de saída do laço. Poço selecionar se o a condição de saída será pré-teste ou pós-teste ou mesmo colocar em uma posição central do laço para interrompê-lo. Do ponto de vista prático de programação é a melhor forma de laço. E foi este tipo de laço que o artigo trata. Não se trata de fazer código "espaguete" como mencionado.

A teoria está muito bem, mais uma vez. O exemplo prático escolhido é que, permita-me discordar, não a demonstra nada. Você criou um ciclo através do goto. Acha tal ciclo um bom exemplo? Eu cá acho um péssimo exemplo.

Eis aquilo que considero um bom exemplo de interrupção de ciclos a meio de uma iteração (ciclo selectivo). Dependendo do estilo do programador, ele poderá ter de fazer uma coisa destas num parser de expressões:

while i <= length(expr) do begin
  token := expr[i];
  // analisa o token

  (* Dependendo da análise, teremos várias condições de interrupção do ciclo
     que devem ser analisadas antes de o colocar na stack. *)

  stack.push(token);
  // etc...

  inc(i);
end;

Isto é um exemplo muito diferente disto...

(* código esparguete *)
n:=1;
ciclo:
writeln(i);
inc(i);
if n<10 then goto ciclo;

(* o que está correcto *)
for n:=1 to 10 do
  writeln(i);

Creio ter deixado claro que o exemplo prático foi o que me deixou desiludido com o artigo. Agradeço a lição teórica bem como o livro teórico recomendado.

Sem mais,

Endereçando os meus melhores cumprimentos,

thoga31.

Editado por thoga31

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1140
HappyHippyHippo

Quando falamos em laços para repetição temos que considerar a existência de seis formas de laço, sendo dividido nas categorias: condicional e incondicional.

Laço incondicional só há um o PARA (for). No entanto a categoria condicional possui 5 laços, sendo 2 do tipo pré-teste (um com fluxo operacional quando condição verdadeira e outro quando condição falsa), 2 do tipo pós-teste (um com fluxo operacional quando condição verdadeira e outro quando condição falsa) e o laço seletivo.

Se eu estiver a considerar que se está a referir a elementos genéricos de programação associados a nenhuma linguagem de programação específica, então compreendo a existência dos 6 ciclos/estruturas de controlo (laços).

Se bem que o selectivo, se é apresentado como descrito no primeiro post, não se enquadra a 100% na sua definição. A única instrução a ser executada na validação é o salto, o incremento deverá ser feito entre o label e a verificação/condição. Se o uso deste tipo de código é delicado, então que se tenha o máximo de cuidado a usa-lo.

A instrução goto existe por razões obvias. Não é um desvaneio dos criadores das linguagens. Basta ler um pouco sobre instruction sets dos processadores e descobresse que sejam estruturas de controlo condicionais (if's) ou ciclos, as coisas funcionam com goto's. Ou seja, a instrução existe porque tem uma relação quase directa com instruction sets assim como é muito usado para criação de código optimizado.

No entanto, para quem ainda não tem traquejo na matéria, frizo : "se não sabes exactamente o que estás a fazer, por favor, não penses sequer em usar"

Agora o ponto que me levou a escrever esta resposta.

o ciclo for ser incondicional ?

ora deixa ca ver os vários tipos de ciclo for que conheço em várias linguagens e suas implementações:

>> C/C++/C#/PHP/Java/Javascript:

- PARA conjunto_de_instrucoes_iniciais ENQUANTO condicao_de_execucao ENTAO conjunto_de_instrucoes_do_ciclo

aqui temos claramente a condição apresentada após a palavra ENQUANTO

// for (<ĩnicialização>;
//      <condição>;
//      <incremento>)
// { }

int i;
for (i = 0;
    i < 19;
    i++)
{
}

>> VB.Net

- PARA variavel DE valor_inicial ATE valor_final [COM incremento]

aqui a condição não é clara como anteriormente, mas com um pouco de atenção, a condição aparece claramente em ATE valor_final

// For <variavel> = <valor_inicial> To <valor_final> [step <incremento>]
//    ...
// Next

Dim i as Integer
For i = 1 To 4

Next

>> lua

- PARA variavel DE valor_inicial ATE valor_final [COM incremento] FAZER

Assim como o VB.Net, volta a aparecer o ATE valor_final, que não deixa de ser uma condição.

// for <variavel> = <valor_inicial>, <valor_final>[, <incremento>] do
//
// end

for i = 0, 10, 2 do

end

Vou ficar por aqui na exposição do ciclo for.

Para finalizar, fica só aqui um parágrafo de um livro que recentemente me foi pedido para escrever uma análise para a revista deste fórum, da qual resultou umas respostas não tão agradáveis da autora, assim como um exemplo para considerar sobre o parágrafo apresentado:

ESTRUTURAS REPETITIVAS CONTROLADAS POR CONTADOR AUTOMÁTICO

Nas estruturas repetitivas controladas por contador automático - estruturas for - a instrução de controlo de ciclo indica explicitamente quantes vezes o ciclo será executado. Contém uma variável designada por contador automático que vai contando as execuções do ciclo. Para cumprir esta função, o contador:

- Assume um valor inicial;

- É incrementado (ou decrementado) automáticamente de cada vez que o ciclo se executa, até atingir o valor final

- Toma o valor final e o ciclo é executado pela última vez

/* Livro de Java => exemplo em Java
*
* se fosse numa lingaugem com ponteiros, a demonstração ainda era mais caricata
*/

import java.util.*;

public class DigraphRunner {
   public class Node {
       public int value;
       public int next;
       public boolean account_jump;

       public Node (int value, int next, boolean account_jump) {
           this.value = value;
           this.next = next;
           this.account_jump = account_jump;

           System.out.println("No criado com o valor de (" +
                              value +
                              ") com salto para (" +
                              next +
                              ") " +
                              (account_jump ? "contabilizando o salto" : "sem contabilizar o salto"));
       }
   }

   public void run() {
       Scanner scanner = new Scanner(System.in);

       System.out.println("Insira o número de nós : ");
       int node_count = scanner.nextInt();

       System.out.println("Insira o valor máximo de cada nó : ");
       int node_max = scanner.nextInt();

       System.out.println("Insira o nó inicial : ");
       int index = scanner.nextInt();

       System.out.println("Insira o valor limite a ser contabilizado : ");
       int max_value = scanner.nextInt();

       System.out.println("Insira o valor máximo de saltos contabilizados : ");
       int max_jumps = scanner.nextInt();

       Random random = new Random();

       System.out.println();
       Node[] nodes = new Node[node_count];
       for (int i = 0;
            i < node_count;
            i++) {
           nodes[i] = new Node( random.nextInt(node_max), random.nextInt(node_count), random.nextBoolean());
       }
       System.out.println();

       int jumps, value;
       for (jumps = 0, value = 0;
            jumps < max_jumps && value < max_value; // quantas iterações foram efectuadas ?
            ) {                                 // onde está o "incremento automático"
           value += nodes[index].value;
           index = nodes[index].next;
           if (nodes[index].account_jump) {
               jumps++;
           }
       }
       // foi executado um último ciclo após tomar o "valor final" ?

       System.out.println("Foram contabilizados " + jumps + " saltos");
       System.out.println("O valor contabilizado foi de : " + value);
   }

   public static void main(String[] args) {
       DigraphRunner runner = new DigraphRunner();
       runner.run();
   }
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Augusto Manzano    0
Augusto Manzano

Prezado Thoga31.

Espero sinceramente ter respondido. A intenção do artigo é em relação a apresentar o uso de uma estrutura de laço seletivo em linguagens que não o possuam. na minha humilde opinião este tipo de laço é o melhor, pois da muita liberdade de ação condicional no código de programa. Pena que poucas linguagens o utilizam. Não escrevi o artigo para criar polêmica ou desgostos aos que não concordam com o uso de "goto". Sei que se não se souber fazer uso deste recursos ter-se-á então um código desestruturado.

Mas gostaria de um favor. Que me desse um bom exemplo de comando "goto".

Abraços.

Quero ainda esclarecer que o chamado "laço seletivo" assim é chamado pela possibilidade de se escolher (selecionar) dentro do bloco a linha onde constará a condição para encerramento do mesmo.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Volta-me a falar da intenção do artigo. O mundo está cheio de boas intenções, isso não temos dúvidas. A intenção já entendi assim que li o artigo. Caso ainda não tenha percebido, eu concordei plenamente consigo na teoria.

Mas voltou a não falar daquilo que suscitou a minha opinião: a simulação de um ciclo, qualquer que ele seja, é um bom exemplo a dar acerca do goto? Se sim, porquê?

Friso que referiu no artigo que tal exemplo era "uma aplicação adequada para o comando goto" - quero saber porque acha isso. Não se desvie deste ponto, que é o cerne da minha opinião.

Mas gostaria de um favor. Que me desse um bom exemplo de comando "goto".

Até hoje nunca encontrei uma situação em que sentisse necessidade de utilizar o goto em detrimento de outras opções. Com isto não quero dizer que não existam situações em que se torna útil, mas graças ao Paradigma Estrutural, em alguns anos de programação nunca necessitei. Só o utilizei no TI-Basic Z80 uma vez que nele não há o conceito de procedimentos ou funções, e a sua simulação era feita com labels.

Cumprimentos.

Editado por thoga31

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pwseo    223
pwseo

Bom dia,

O exemplo apresentado na revista não é (de todo!) uma boa aplicação do comando goto.

Mas já que foi pedido, deixo um exemplo de uma boa aplicação: imaginemos que temos vários ciclos encadeados e, no mais profundo deles, queremos terminar todos os ciclos quando se verifica uma determinada condição. Numa linguagem que permita fazer um break selectivo (que é conhecido como labelled break) não há problema, mas caso break apenas termine o ciclo no qual é invocado, a solução mais legível será utilizar goto (que, já agora, é a verdadeira identidade de um labelled break), permitindo que a execução salte para fora de todos os ciclos numa única instrução.

Um exemplo retirado da wiki da linguagem:

for z=1,10 do
for y=1,10 do
for x=1,10 do
 if x^2 + y^2 == z^2 then
   print('found a Pythagorean triple:', x, y, z)
   goto done
 end
end end end
::done::

A Wiki da linguagem Lua contém vários exemplos de utilizações correctas do goto (os meus exemplos preferidos são os de terminação de ciclos encadeados e para error-handling e cleanup em funções).

Logicamente, todos os exemplos poderiam ter sido escritos com estruturas de controlo "menos heréticas", mas isso levaria a código menos compacto e menos legível (e até mais lento, mas nem vou colocar essa questão).

tl;dr O goto é uma arma potente e muito facilmente mal utilizada. Se não soubermos o que estamos a fazer, o melhor mesmo é não utilizar.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Augusto Manzano    0
Augusto Manzano

Olá a todos.

O exemplo apresentado por pwseo é um excelente exemplo. Na linguagem BASIC em modo estruturado (Structured BASIC, encontrado no ambiente de desenvolvimento VS - Visual BASIC) há o comando "Exit For". Em Lua e outras linguagens essa possibilidade não existe.

Creio que o tema já foi bem discutido e estamos a esbarrar em concepções pessoais que não levará além do ponto em que chegamos. Há quem goste do goto há quem o odeie. Não sei como surgiu o conceito que não se usa comando goto em linguagens estruturadas. Fica a questão, por qual motivo ele então existe nessas linguagens?

Quando escrevi o artigo não estava em um devaneio ou em um momento de má inspiração. O fiz com a mesma certeza dos outros artigos que escrevi para a revista. Com a mesma certeza dos livros que escrevi ou das aulas que ministro. Sabia que o que coloquei poderia criar certa polêmica e isso não me preocupa.

A estrutura básicas de controlo de ciclo (em Portugal) ou estruturas de laço (no Brasil) são bem conhecidas como: "while"; "do ... while" (em C) ou "repeat ... until" (em Pascal), que são em Pascal e C ciclos antagônicos, pois em Pascal o ciclo ocorre para a condição falsa e em linguagem C o ciclo ocorre para a condição verdadeira e por último o comando "for". O que muitos programadores não conhecem são as outras três formas de controlo de ciclos (laços), que são:

estruturas repetitivas pré-teste com bloco executado para a condição sendo verdadeira - while (condição)... end_while;

estruturas repetitivas pré-teste com bloco executado para a condição sendo falsa - until (condição) ... end_until;

estruturas repetitivas pós-teste com bloco executado para a condição sendo verdadeira - do ... while (condição);

estruturas repetitivas pós-teste com bloco executado para a condição sendo falsa - repeat ... until (condição);

estruturas repetitivas controlo de ciclo seletivo loop ... exit loop (condição) ... end_loop;

estruturas repetitivas controladas por contador automático for ... next_for.

Muitos podem não concordar com o conjunto existente, mas eles existem e são encontrados em maior ou menor proporção. Cabe a um programador de computador conhecê-los e fazer uso. Um dia desses me perguntaram: Você é programador de computador? Respondi que sim. Veio a segunda pergunta. Em que linguagem? Respondi qualquer uma, Veio a terceira pergunta: Como assim? Respondi,programo computadores, a linguagem para mim é mera ferramenta para concretização do código.

Em referência a pergunta de Thoga31

Friso que referiu no artigo que tal exemplo era "uma aplicação adequada para o comando goto" - quero saber porque acha isso. Não se desvie deste ponto, que é o cerne da minha opinião.

No último artigo, até o momento, em que publiquei acerca de uso da linguagem Lua fiz referência a estrutura de repetição de controlo de ciclo seletivo que existe sintaticamente nas linguagens ADA e Structured BASIC, mas não é encontrada em diversas outras linguagens, pelo menos do universo que conheço. O fato de outras linguagens não possuírem essas estrutura não significa que essa estrutura não possa vir a ser utilizada.

Eu não sei se estou me fazendo entender, creio que até o presente momento isso não ocorreu. Talvez a questão seja em relação a concepção de códigos de programas a partir de estruturas de controle menos populares para o atual grupo de programadores.

Quando aprendi a primeira linguagem de programação, isso nos meus 18 anos de idade, tive aulas com professores que atuavam na área de computadores de grande porte. Aprendi, e uso até hoje, a fazer a concepção de programas com diversas documentações incluindo-se o uso de diagramas (flowcharts) dentro das especificações da norma ISO 5807. Há uma máxima que reza que o papel aceita tudo. Isso é verdade. Dependendo da necessidade operacional o desenho de um código (nas especificações ISO 5807) pode assumir uma das formas de çontrolo de ciclos citadas e nem todas são encontradas em uma ou outra linguagem de programação. No momento de se fazer a codificação do programa deve-se manter a linha do projeto desenhada (é como a construção de uma casa).

Desta forma, nem todas as linguagens de programação possuem ferramentas para a definição dessas construções. É ai que entram o uso do operador de negação condicional de uma linguagem (not) para simular por exemplo em linguagem C uma estrutura de controlo de ciclos pós-teste com bloco executado para a condição sendo falsa, estilo repeat ... until, que assim ficaria escrito:

do

{

bloco;

}

while (!(condição))

Assim, se no projeto diagramado for desenhado a estrutura de um controlo de ciclo em estilo seletivo, sua implementação numa linguagem que não o possua será feita com o uso do comando "goto".

Numa linguagem de tipo estruturado há poucas possibilidades de uso do comando "goto": são duas, talvez três ocorrências. Uma delas, a mais comum, é a que mostrei no artigo: simulação de execução de ciclo de controlo seletivo, que resumi-se em encerrar a execução de um laço, que corresponde ao exemplo mostrado por pwseo numa outra dimensão. A segunda ocorrência de uso de "goto" em uma linguagem estruturada não cabe discutir, pois é especifica para aplicações em baixo nível.

Não há para mim, melhor ou pior linguagem de programação. Há linguagens mais usadas e menos usadas, mais conhecidas e menos conhecidas. Pouco me importa a linguagem a ser usada, o que interessa é o produto final. Na medida em que aprendemos várias linguagens nossa mente se abre a outros pontos de vista e nos proporciona maiores visões acerca deste conhecimento.

Quem quiser pode ver o catálogo "The language list" (http://people.ku.edu/~nkinners/LangList/Extras/langlist.htm) que possui informações curtas sobre 2500 linguagens de programação. No entanto, há muito mais linguagens para programação. Cada qual com sua potencialidades e fraquezas. A ciência em programação está em combinar paradigmas para extrair o melhor de cada ferramenta e não se fechar em um outro outro modelo de programação. Convido ainda a ler o artigo "Teach Yourself Programming in Ten Years" (http://norvig.com/21-days.html).

Espero ter esclarecido. Um abraço a todos.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pwseo    223
pwseo

Augusto Manzano,

Vou ser honesto. Não compreendo por que motivo estamos a discutir diferentes tipos de ciclos quando a thread foi iniciada porque um membro/leitor (thoga31) achou que o exemplo dado na revista era inadequado. Reformulando: ninguém colocou em causa a utilidade do goto, apenas o exemplo que foi dado da sua utilidade.

Se a linguagem que utilizamos possui um mecanismo de ciclo dependente de um contador, não há motivo nenhum para simularmos esse mecanismo nós mesmos via goto; se o fizermos, apenas aumentaremos o tamanho do código e diminuiremos a legibilidade do mesmo, sem qualquer ganho na eficiência do programa.

Ao contrário do exemplo que dei com três níveis de ciclos (e dos exemplos presentes na wiki, cujo link já referi anteriormente), o exemplo que o Augusto deu na Revista pode ser facilmente re-escrito com estruturas de controlo de fluxo já existentes na linguagem de forma muito mais legível, colocando em causa a utilidade do exemplo que deu.

Mais concretamente, nunca ninguém iria escrever isto:

I = 1
::PontoRetorno::
print(string.format("%2d", I))
if (I < 10) then
  I = I + 1
  goto PontoRetorno
end

quando podia simplesmente escrever isto:

for i = 1, 10, 1 do
  print(string.format("%2d", i))
end

Quero apenas clarificar que é à volta desta questão que gira toda a problemática desta thread.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Bem, eu vou ser muito directo, honesto, sincero e todas as palavras do dicionário afins.

Sr. Augusto Manzano, você insiste em não perceber que nunca foi colocada em causa a existência do goto nem a utilidade do goto. Repito pela enésima vez que nesse aspecto estamos de acordo.

Volto a não perceber porque é que me apareceu à frente, mais uma vez, uma grande exposição teórica acerca de ciclos.

Volto a não perceber porque é que me deparei com mais história das linguagens de programação.

Volto a não perceber porque é que recomenda tanta leitura teórica.

Volto a não perceber porque é que insiste em não perceber, ou não querer perceber, que a minha crítica se centra no exemplo prático.

Volto a não perceber porque é que acha que o exemplo prático que deu no artigo é um bom exemplo de utilização do goto.

Custa assim tanto o Sr. perceber que eu critico o exemplo prático e não a teoria?

Eu vou ser bastante claro e objectivo, para variar dos longos posts aqui presentes, acerca daquele que é o ponto do artigo que critico.

É isto, e só isto, que eu critico:

I = 1
::PontoRetorno::
print(string.format("%2d", I))
if (I < 10) then
  I = I + 1
  goto PontoRetorno
end

Fui claro agora? Pode-me responder de uma vez às minhas perguntas, de preferência de forma concisa e objectiva?

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Augusto Manzano    0
Augusto Manzano

Olá Sr. Thoga31.

Somente quis descrever um uso, não todos os usos do comando goto. Creio queo senhor, talvez, não tenha entendido o motivo do exemplo na parte prática que usei. Quanto a parte teórica tenho certeza de que o senhor entendeu plenamente. Também não quero me estender neste assunto, pois está ficando cansativo de mais. O fato de eu usar um exemplo desconhecido para parte dos programadores, não significa que este tipo de ocorrência não exista ou venha a acontecer. Sei que o exemplo que dei daria para fazer com um laço "for". No entanto, era para ser um simples uso de aplicação para o comando "goto". Não se trata de ser teórico, pois a teoria dá a base para que a prática seja executada. Não concordo com o dito de ser a prática melhor que a didática, como alguns se referem muitas vezes.

Como professor, considero seu questionamento ou crítica (se assim deseja) como dúvida de um aluno. Assim, vou passar um desafio ao senhor como sendo meu aluno. O programa a seguir está escrito em Structured BASIC na versão do ambiente QBASIC e usa laço "do ... loop". Por favor, codifique o programa em Lua ou mesmo em C sem usar coisas do tipo: while (true) ou do ... while (true) ou outras tentativas afins, como o uso de um "for". Faça a solução com uso de "goto" e creio que entenderá a abrangência prática do exposto.

Vamos a um cenário hipotético, mas prático.

Considere o problema a seguir relacionado a um código legado de uma empresa em uma causa judicial, que necessita ser reescrito em Lua ou C para análise jurídica mantendo-se seu formato original, pois assim, está definido na sua documentação de sistemas e não pode ser alterado para outro formato linguístico por qualquer motivo. É necessário manter-se esta conduta para a continuidade da defesa do processo contra a empresa perpetrada pelo cliente. Você é o especialista eleito pelo juiz para dar apoio aos trabalhos de perícia técnica e deverá manter a linha lógica original inalterada, mesmo no código traduzido em Lua ou C.

REM LACO SELETIVO

DIM r AS STRING

DIM n AS INTEGER

DIM x AS INTEGER

DIM i AS INTEGER

CLS : i = 1

DO

PRINT USING "Entre valor ##"; i: INPUT "-> ", n

x = n * 3

PRINT USING "Resultado = ###"; x: PRINT

INPUT "Deseja continuar? (S) para Sim, qualquer letra para Nao: ", r

PRINT

IF (UCASE$® "S") THEN EXIT DO

i = i + 1

LOOP

END

Somente uma observação. Devido a formatação de caracteres no sistema talvez não seja apresentado corretamente o operador de diferença da condição da linha IF ou a variável "r" como símbolo de marca registrada. Assim, considere como condição UCASE$® <> "S".

UCASE$( r ) <> "S"

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

A prática complementa a teoria, e se a prática não mostra bem o que se pretende transmitir com a teoria, então teremos um problema. Enquanto professor, deveria saber isto melhor que ninguém. Uma excelente área em que isto é mais-que-verdade é a Química Orgânica. Mas como eu não pretendo ser uma enciclopédia nem despejar aqui o conteúdo de uma, não vou estar a falar acerca da teoria de reacções. Da mesma forma, na Programação a prática é muito importante: ainda não vi nenhum software feito só com teoria, acho que desde sempre se fez com código - e o código é a parte prática, a qual reflecte a teoria. Ou não é?

Considero que foi o que se passou no seu exemplo no artigo - falhou a mostrar na prática um exemplo de bom uso. Queria um exemplo simples? Olhe para o do @pwseo, é simples e é um bom exemplo prático que demonstra bem o que a teoria nos diz.

Como professor, considero seu questionamento ou crítica (se assim deseja) como dúvida de um aluno. Assim, vou passar um desafio ao senhor como sendo meu aluno. O programa a seguir está escrito em Structured BASIC na versão do ambiente QBASIC e usa laço "do ... loop". Por favor, codifique o programa em Lua ou mesmo em C sem usar coisas do tipo: while (true) ou do ... while (true) ou outras tentativas afins, como o uso de um "for". Faça a solução com uso de "goto" e creio que entenderá a abrangência prática do exposto.

Primeiro que nada, não sou seu aluno e não quero que me considere seu aluno, da mesma forma que não o considero meu professor. Considere-se o autor de um artigo de programação publicado numa revista com milhares de leitores, e considere-me um desses leitores. É neste estatuto que estamos aqui.

Segundo, outra vez a simular ciclos com goto? Really?

Adorei o facto de ter tentado mostrar a utilidade do goto num exercício que faz um ciclo proibindo expressamente... o uso dos ciclos que existem nas linguagens! Muito bom.

Terceiro, quanto ao seu caso hipotético continuaria a utilizar break pois é um único ciclo. De qualquer das formas, adorei o "discurso judicial".

Quarto, continua a querer que eu "perceba a abrangência do goto" (a forma como agora tentou fazê-lo já acabei de comentar) - qual é a parte de "eu sei que há usos práticos" que não entendeu? Porquê tentar ensinar algo que eu já sei? Só porque eu ainda não necessitei de usar? Ok, então acha que é a simular ciclos que vou ver tal abrangência? Três letras: LOL.

Também não quero me estender neste assunto, pois está ficando cansativo de mais.

Termino citando esta sua frase, pois cansado estou eu. A minha opinião está dada, e não fui o único a pensar da mesma forma, e tenho a certeza que me fiz compreender uma vez que colegas aqui do fórum entenderam o que eu pretendi dizer.

Se quer perceber, perceba. Se quer insistir na mesma tecla, fique com a sua que eu fico com a minha. Aquilo que me está a fazer crer é que quer fazer valer a sua até ao fim.

Este debate, que infelizmente está a ser infrutífero e possivelmente tóxico para aprendizes que estejam a ler, apenas me está a ajudar a confirmar que o ensino da programação está a viver dias de Primavera... uma Primavera chuvosa e cinzenta, confirmada por muitos alunos que vêm aqui ao P@P tirar as suas dúvidas.

Uma vez que a minha crítica está dada, assim como a minha opinião, saio deste tópico.

P.S. - use as tags CODE, indicando a linguagem, para que o código apareça correctamente e com highlight.

Editado por thoga31

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Augusto Manzano    0
Augusto Manzano

Olá,

Sinceramente acho que isso virou um caso pessoal de sua parte em relação a minha pessoa. Não sei o motivo. O senhor me fez uma pergunta, tentei responder e exemplificar o mais cordial possível e da melhor maneira possível e deste seu primeiro contato não foi o mesmo que percebi de sua parte e em seu discurso, lamento muito por isso, como moderador sua posição é apaziguar discussões acaloradas, é por água fria na fervura. E não estamos conseguindo nos entender. No último post dei um exemplo prático, como solicitado pelo senhor e citado por outros do que seria um "bom" uso de comando "goto". O exemplo, o desafio está aberto a qualquer pessoa que queira respondê-lo. A situação exposta embasa o uso de um bom uso de "goto", numa situação mesmo que rara. Basta tentar codificar em Lua, C, C++, Pascal e a resposta surgirá automaticamente.

Como professor, sou um pescador. Ensino a pescar, mas não dou o peixe.

Acredito que respondi seu questionamento, mas quando "o aluno" não quer ouvir um professor. Não há força na natureza que proporcione aprendizagem e possibilidade de compreensão acerca das questões levantadas. A partir deste ponto, gera-se apenas palavras mortas.

O exemplo de bom uso uso de "goto" que o senhor cita não é da pessoa citada mas de uma fonte chamada wiki lua que ela fez a pesquisa. Teve a curiosidade de buscar um exemplo para auxiliar sua dúvida.

Lamento que estejamos perdendo um precioso tempo por causa de um ínfimo comando que alguns usam e outros não. Que bom é a liberdade e o livre arbítrio, pois podemos escolher o que gostamos ou não de fazer e/ou usar.

Para mim esta questão está encerrada, pois não vamos chegar a lugar nenhum. Creio que o foco e objetivo deste espaço esteja se perdendo. Estou aberto para dirimir outras dúvidas ou questões de modo que seja respeitoso entre nós. Não quis ofendê-lo em momento algum, se assim se sentiu me perdoe.

Abraços.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
thoga31    594
thoga31

Bem, sou obrigado a responder...

Eu não sei o motivo pelo qual pensa que isto virou um caso pessoal.

O meu papel enquanto Moderador é uma coisa. O meu papel enquanto leitor é outra. As pessoas estão sempre a confundir as coisas, e de uma forma ou de outra a história de ser Moderador há-de vir ao de cima. Ser Moderador não tem nada a ver com o assunto que nos trouxe até aqui.

Se não nos estamos a entender o motivo é simples: eu disse que não concordava com o exemplo prático exposto no artigo, e você deu-me uma aula de ciclos, leituras recomendadas e tudo o que havia direito. Mais, deu-me exercícios para entender a abrangência do goto, coisa que não era o assunto do tópico, tendo por base precisamente aquilo que eu critiquei - simulação de ciclos.

Regra geral, se uma pessoa pergunta acerca de vinhos e o outro responde com astronomia, é normal que não se entendam.

Mais, eu não pedi exemplos, quem pediu foi você. Eu pedi que me explicasse onde é que a simulação de ciclos é um bom exemplo. Por outras palavras, gostaria que reflectisse o seu exemplo do artigo.

Já agora, o exercício dado é, desculpe que lhe diga, genial. Você pede a simulação de um ciclo proibindo expressamente o uso de ciclos! Faz sentido?

Deixe-me localizá-lo: o professor não está a ser capaz de entender o ponto de vista do aluno nem de argumentar na mesma linha de pensamento.

E entretanto até já vamos ao pormenor... Sim, eu sei que veio da Wiki Lua. Quando referi o exemplo do @pwseo, referia-me obviamente a um exemplo da Wiki Lua. Não sejamos mais papistas que o Papa! E diga-se, o @pwseo foi capaz de ir buscar a um bom recurso online um bom exemplo de uso do goto.

E eu não tinha nenhuma dúvida, eu questionei foi o seu código do artigo (quantas vezes já disse eu isto...?)

Também como já foi dito, inclusive por si, este "ínfimo comando" deve ser utilizado com muito cuidado e não levianamente como muita gente faz. Portanto, não é um "ínfimo comando", é um comando muito útil mas muito perigoso - a sua margem de segurança de utilização é mínima.

Como disse antes, se as duas pessoas falam de coisas diferentes, não se vai longe. O objectivo perdeu-se a partir do momento em que decidiu expor uma grande lição acerca de ciclos e do goto em vez de se centrar no tema inicial do tópico.

Eu espero que fique claro que não me ofendeu. Apenas lamento que não se tenha focado naquele que foi o código que me suscitou a crítica.

De qualquer das formas, eu já estou esclarecido: utilizou um exemplo simples e continua a achar que é bom. Pronto, os criadores do Paradigma Estrutural agradecem-lhe.

Nota: até na primeira versão do BASIC havia o ciclo FOR, e era o BASIC, a linguagem dos GOTO's por excelência... Simular um ciclo FOR em Lua com GOTO, e depois estar aqui sempre a falar do BASIC é, no mínimo, irónico.

Editado por thoga31

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
apocsantos    211
apocsantos

Boa noite,

Depois de tanto ler, gostava de começar por citar parte do texto, onde me revi pessoalmente:

Um dia desses me perguntaram: Você é programador de computador? Respondi que sim. Veio a segunda pergunta. Em que linguagem? Respondi qualquer uma, Veio a terceira pergunta: Como assim? Respondi,programo computadores, a linguagem para mim é mera ferramenta para concretização do código.

Existem N exemplos para se usar goto, apesar desta instrução ter dado origem a muito mau código, mas não sendo de todo uma má instrução, que encontra o seu fundamento nas instruction sets dos processadores. Em MIPS por exemplo

jr $s

é o mesmo que ter

goto $s

ou

LOOP 

em x86 (8086 / 8088).

Pedia que não entrassem em discuções tão pessoais como as que li acima. Todos temos direito de gostar ou desgostar, mas a critica construtiva, deve permanecer construtiva e a duvida esclarecida.

Infelizmente o uso excessivo do goto deu origem a muito "codigo esparguete", mas não considero o uso de goto como um "sacrilégio". Lembro-me de usar e abusar do goto em Basic no Spectrum, expecialmente quando comecei a programar.

Exemplo de um uso de goto em Basic no spectrum, era algo do genero:

5 REM "CODIGO EXEMPLO"
10 PRINT "UMA TECLA PRIMIDA"
15 PRINT "Apenas um exemplo"
16 IF INKEY$ ="" THEN GO TO 20
17 IF INKEY$ <>"" THEN GO TO 10
20 PRINT "fim de loop"

Existiam N formas de fazer este mesmo exemplo com outros tipos de ciclos, mas também é possivel com goto.

@Thoga31: Enquanto autor de vários artigos, sabes que um autor está sempre cheio de boas intenções, mas nem sempre são compreendidas pelos leitores. Eu também o sinto, porque também sou autor.

Agradeço a todos a participação na revista e peço um pouco mais objectividade nos comentários e respostas aos mesmos.

Coordiais cumprimentos,

Apocsantos

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.