Perl – Laço redo com Tk e subrotina

Neste exemplo um laço redo foi simplificado, colocado em uma subrotina e exibido via interface gráfica.

Design-time

#!/usr/bin/perl
use warnings;
use strict;
use Tkx;

my @a = (9,3,2,4,6,5,8,7,1);
my ($num, $pos);

Tkx::wm_title(".", "Redo loop");

Tkx::grid(Tkx::ttk__frame(".c"));

Tkx::grid(Tkx::ttk__label(".c.l0", -text => "Array: "), -row => 1, -column => 1);

Tkx::grid(Tkx::ttk__label(".c.l1", -text => "(@a)"), -row => 1, -column => 2);

Tkx::grid(Tkx::ttk__label(".c.l2", -text => "Procurar: "), -row => 2, -column => 1);

Tkx::grid(Tkx::ttk__entry(".c.e1", -textvariable => \$num), -row => 2, -column => 2);

Tkx::grid(Tkx::ttk__button(".c.b1", -text => "Executar", -command => sub {encontrar();}), -row => 3, -column => 2);

Tkx::grid(Tkx::ttk__label(".c.l3", -text => "Elemento: "), -row => 4, -column => 1);

Tkx::grid(Tkx::ttk__label(".c.l4", -textvariable => \$pos), -row => 4, -column => 2);

sub encontrar{
	$pos = -1;
	{
		$pos++;
		redo if $pos < scalar @a && $a[$pos] != int($num);
	}
	if($pos < scalar @a){
		$pos;
	}else{ $pos = "Fora do array";}
}

Tkx::MainLoop();

Runtime

Perl + Tkx rodando no Ubuntu 22.04 (Jammy Jellyfish), captura com Peek

Sintaxe

O bloco (entre as linhas 29 e 32) está simplificado, sem next e sem last, com suas duas condicionais em uma mesma instrução (linha 31). A primeira condicional verifica se a variável $pos tem um valor menor do que o tamanho do array. A segunda condicional compara o valor informado aos elementos do array.

Antes de retornar o valor de $pos, a subrotina (linhas 27-36) verifica este valor através da condicional if-else (linhas 33-35).

Observe as linhas em destaque (4, 9-25, 38) contendo as instruções que constroem a interface gráfica do usuário com a Tk toolkit.

Reflexão

Por que será que no Brasil uma parcela representativa dos evangélicos está associada à lavagem de dinheiro, a traficantes, a milicianos, a terroristas e à extrema-direita?

https://www1.folha.uol.com.br/poder/2023/02/ha-muita-gente-boa-presa-apos-o-81-diz-novo-presidente-da-bancada-evangelica.shtml

Perl – Laço redo com next e last – parte II

Neste exemplo foi combinado um laço redo com next e last em apenas um bloco e também foi incluída uma mensagem necessária quando um item não estiver na lista, ou melhor, um elemento não for encontrado no array.

  • Design-time
my @a = (9,3,2,4,6,5,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = 0;
[bloco:]{
    	last | next if $a[$pos] == $num;
	    $pos++;
	    redo [bloco] if $pos < scalar @a;
}

if($pos < scalar @a){
	print "Número $num encontrado na posição $pos\n";
}else{
	print "Número $num não encontrado\n";
}
  • Runtime

Preview in new tab

  • Sintaxe

Observe na listagem acima a linha 1 em destaque porque nela propositalmente foi retirado ou não existe o elemento 8, número que é procurado na segunda vez em que o programa roda – ver runtime ilustrado acima.

Também estão em destaque as linhas 17-21 com as opções de encontro ou não do número procurado.

A identificação do bloco com um rótulo (ou label) pode ocorrer nas linhas 11 e 14, e não afeta o comportamento da aplicação (ou programa).

A linha 14 poderia ser invertida: if($pos < scalar @a){redo [bloco]};

  • Reflexão

A extrema direita incentiva a pena de morte, a posse e o livre porte de armas, e o trabalho escravo. Não é apenas nos Estados Unidos que ainda existe escravidão, embora lá oficialmente “apenas os prisioneiros condenados” são submetidos a trabalho forçado.

https://noticias.uol.com.br/colunas/leonardo-sakamoto/2023/02/25/escravizados-na-producao-de-vinho-no-rs-recebiam-choques-e-spray-de-pimenta.htm

https://g1.globo.com/mundo/noticia/2022/11/07/eleicoes-nos-eua-por-que-escravidao-e-tema-de-plebiscitos-em-5-estados.ghtml

Perl – Laços redo com next e last

É possível combinar redo com next e last. Neste exemplo, estas opções estão em um bloco interno.

  • Design-time
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = 0;
[bloco:]{
    {
		next | last if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
	redo [bloco] if $pos < scalar @a;
}
  • Runtime
  • Sintaxe

Observe na listagem acima a linha 13 em destaque, dentro do bloco interno entre as linhas 12 e 15. A instrução next realiza um salto para o fim do bloco, ignorando a instrução print da linha 14. A instrução last realiza um salto para fora do bloco interno, e neste caso tem o mesmo efeito.

De qualquer forma, o contador $pos é incrementado até o fim da lista, isto é, até atingir o valor equivalente ao tamanho do array (scalar @a).

A identificação do bloco com um rótulo (ou label) pode ocorrer nas linhas 11 e 17, e não afeta o comportamento da aplicação (ou programa).

A linha 17 poderia ser invertida: if($pos < scalar @a){redo [bloco]};

  • Reflexão

Que tal falarmos mais um pouco do obscurantismo que passamos nos últimos 4 anos, e sobre negacionismo, terraplanismo, extremismo, ignorância e alienação? É ou não é uma questão de ciência?

Perl – laços com redo

É possível construir loops (laços) sem for, foreach, while, do while, until e do until. Neste exemplo há uma estrutura de controle de repetição ou iteração com o comando redo. Este comando reinicia incondicionalmente um laço, isto é, salta para a primeira instrução dentro do bloco.

  • Design-time
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = 0;
[bloco:]{
	if($a[$pos] == $num){
		print "Número $num encontrado na posição $pos\n";
		[exit;]
	}
	$pos++;
	redo [bloco] [if $pos < scalar @a];
}
  • Runtime
  • Sintaxe

Observe na listagem acima as linhas em destaque. As instruções ou comandos entre ou dentro de colchetes são opcionais.

A identificação do bloco com um rótulo (ou label) pode ocorrer nas linhas 11 e 17, e não afeta o comportamento da aplicação (ou programa).

A linha 17 poderia ser invertida: if($pos < scalar @a){redo [bloco]};

A tabela a seguir ilustra as diversas opções de uso ou não das instruções exit na linha 14 e if($pos < scalar @a) na linha 17, quando um determinado número existe ou não na lista, e o que ocorre com o laço, se finaliza e termina o programa ou não.

#exitif(… scalar @a)$num existe ?laço finito?
1nãonãonãonão
2nãonãosimnão
3simnãonãonão
4simnãosimsim
5nãosimnãosim
6nãosimsimsim
7simsimnãosim
8simsimsimsim

A melhor opção seria um bloco da seguinte maneira, sem rótulo (já que é o único, não contém outro e não está contido em outro bloco), sem exit, e com if($pos < scalar @a):

{
	if($a[$pos] == $num){print "Número $num encontrado na posição $pos\n";}
	$pos++;
	redo if $pos < scalar @a;
}
  • Reflexão

A seguir estão imagens capturadas quando fiz um consulta ao ChatGPT. Tire suas próprias conclusões.

Perl – Laços com last

Neste exemplo está resumido o uso da instrução last em diversas estruturas de repetição (forwhileuntildo while e do until).

Design-time

  • Listagem I
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = -1;

#1 - for
foreach(@a){	
    $pos++;
    last if $_ == $num;
}

#2 - while
while($pos < scalar @a - 1){
    $pos++;
    last if $a[$pos] == $num;
}

#3 - until
until($pos == scalar @a - 1){	
    $pos++;
    last if $a[$pos] == $num;
}

#4 - do while
{
	do{
		$pos++;
		last if $a[$pos] == $num;
	}while($pos < scalar @a - 1)
}

#5 - do until
{
	do{
		$pos++;
		last if $a[$pos] == $num;
	}until($pos == scalar @a - 1)
}

print "Número $num encontrado na posição $pos\n"
  • Listagem II
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = 0;

#1 - for
foreach(@a){
	last if $_ == $num;
	$pos++;
}

#2 - while
while($pos < scalar @a){
	last if $a[$pos] == $num;
	$pos++;
}

#3 - until
until($pos == scalar @a){
	last if $a[$pos] == $num;
	$pos++;
}

#4 - do while
{
	do{
		last if $a[$pos] == $num;
		$pos++;
	}while($pos < scalar @a)
}

#5 - do until
{
	do{
		last if $a[$pos] == $num;
		$pos++;
	}until($pos == scalar @a)
}

print "Número $num encontrado na posição $pos\n"

Runtime

Sintaxe

As 2 listagens acima, cada uma com 5 alternativas, produzem exatamente a mesma saída (que é a mesma do post anterior), ilustrada acima. Diferença entre as listagens:

Na primeira listagem a variável $pos é definida com o valor -1 (linha 10) e, por isso, sua operação de incremento ($pos++, linhas 14, 20, 26, 33 e 41) deve ser a primeira instrução dentro de qualquer laço.

Na segunda listagem a variável $pos é definida com o valor 0 (linha 10) e, por isso, sua operação de incremento ($pos++, linhas 15, 21, 27, 34 e 42) deve ser a última instrução dentro de qualquer laço, dentro do bloco que contém a combinação de instruções last if. O bloco pode, opcionalmente, ser identificado por um rótulo seguido por dois pontos (nome_do_bloco :).

Observe que os laços do while e do until sempre devem incluir um bloco para last if, externamente, ao contrário do visto no post anterior com next if. Também é externa a instrução print "Número $num encontrado na posição $pos\n" (que, sendo a última, dispensa a inclusão de ponto-e-vírgula).

Reflexão

Hoje em dia está na moda o ChatGPT, celebrado como a cereja do bolo da tecnologia da informação. É interessante, inovador, sim, mas devagar com o andor que o santo é de barro. Em outras palavras, não é um oráculo que sabe de tudo.

Perl – Laços com next

Neste exemplo está resumido o uso da instrução next em diversas estruturas de repetição (for, while, until, do while e do until).

Design-time

  • Listagem I
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = -1;

#1 - for
foreach(@a){
	$pos++;
	next if $_ != $num;
	print "Número $num encontrado na posição $pos\n";
}

#2 - while
while($pos < scalar @a - 1){
	$pos++;
	next if $a[$pos] != $num;
	print "Número $num encontrado na posição $pos\n";
}

#3 - until
until($pos == scalar @a - 1){
	$pos++;
	next if $a[$pos] != $num;
	print "Número $num encontrado na posição $pos\n";
}

#4 - do while e necessário bloco interno
do{
	$pos++;
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
}while($pos < scalar @a - 1)

#5 - do until e necessário bloco interno 
do{
	$pos++;
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
}until($pos == scalar @a - 1)
  • Listagem II
my @a = (9,3,2,4,6,5,8,7,1);
my $num;

print "Array: ( @a )\n";
do{
   print "Informe um número a ser procurado (1-9): ";
   $num = int <>;
}until($num >= 1 && $num <= 9);

my $pos = 0;

#1 - for
foreach(@a){
	{
		next if $_ != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
}

#2 - while
while($pos < scalar @a){
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
}

#3 - until
until($pos == scalar @a){
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
}

#4 - do while
do{
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
}while($pos < scalar @a)

#5 - do until 
do{
	{
		next if $a[$pos] != $num;
		print "Número $num encontrado na posição $pos\n";
	}
	$pos++;
}until($pos == scalar @a)

Runtime

Sintaxe

As 2 listagens acima, cada uma com 5 alternativas, produzem exatamente a mesma saída, ilustrada acima. Diferença entre as listagens:

Na primeira listagem a variável $pos é definida com o valor -1 (linha 10) e, por isso, sua operação de incremento ($pos++, linhas 14, 21, 28, 35 e 44) deve ser a primeira instrução dentro de qualquer laço.

Na segunda listagem a variável $pos é definida com o valor 0 (linha 10) e, por isso, sua operação de incremento ($pos++, linhas 18, 27, 36, 45 e 54) deve ser a última instrução dentro de qualquer laço, após o bloco que contém a combinação de instruções next if. O bloco pode, opcionalmente, ser identificado por um rótulo seguido por dois pontos (nome_do_bloco :).

Observe que os laços do while e do until sempre devem incluir um bloco interno para next if.

O primeiro laço, comum a todas as alternativas, que solicita um número a ser procurado no array poderia ser de outras 3 formas:

do{…}while($num < 1 || $num > 9);

while($num < 1 || $num > 9){…}

until($num >= 1 && $num <= 9){…}

Nas 2 últimas opções (while e until), a variável precisaria ser definida (my $num = 0;).

Observe como as condições diferem ao se usar while e do while (com o operador ||, OR) ou until e do until (com o operador &&, AND), sendo esta última opção mais intuitiva.

Reflexão

Recomendo a leitura do artigo de André Calixtre intitulado “O Fascismo do Século XXI e o papel da Classe Média” porque, como disse a professora Marilena Chauí, “A classe média é uma abominação política, porque é fascista, é uma abominação ética porque é violenta, e é uma abominação cognitiva porque é ignorante.”.

Perl – Laço do until com last

Neste exemplo foi usada a instrução last associada a condicionais (if) para interromper iterações da estrutura de repetição do until em um jogo de adivinhação.

  • Design-time
my $x = int(rand(10));
my $max = 4;
my $attempt = 0;
my $num = 0;

print "Adivinhe qual é o número em até 3 tentativas, (0-9 ou -1 para sair):\n";    

game:{
	do{
	    if($attempt < $max){
           	$num = int(<>); 
           	last if $num == -1; 
           	$attempt++;
		}else{
			print "Game over!\n";
           	last;
      	}

      	if($num < $x){
           	print "Dica: é maior.\n";
      	}elsif($num > $x){
           	print "Dica: é menor.\n";
      	}else{
           	print "Bingo!\n";
      	}
	}until($num == $x);
}
print "Número sorteado: $x\n"
  • Runtime
  • Sintaxe

Este código é uma adaptação do exemplo ilustrado na seção “2) Using do…until with the last statement” do sítio Perl Tutorial.

Observe na primeira linha o uso da função rand para gerar um número inteiro aleatório de 0 a 9, que o usuário deverá adivinhar.

A instrução last interrompe o laço do until caso o usuário digite -1 para sair (linha 12) ou o número de tentativas seja maior do que 3 (linhas 10 e 16).

A função print foi utilizada sem os parênteses. A última linha não foi finalizada com a inclusão do ponto e vírgula.

  • Reflexão

O cristofascismo perdeu a batalha das urnas, mas não está morto; a luta continua. Nunca devemos clamar vitória sobre o cão bastardo, pois a cadela do fascismo que o pariu está sempre no cio. Pedro Aleixo nos ensinou que o problema que deve nos preocupar não são as autoridades maiores, mas sim os guardas da esquina. Não haveria bolsonarismo se não fosse a ignorância, a hipocrisia e o preconceito.