[Cascavel-pm] Procurando chifre em cabeça de cavalo ???

Luis Campos de Carvalho lechamps em terra.com.br
Terça Junho 8 12:26:33 CDT 2004


Solli Moreira Honorio wrote:
> Pessoal,
> 
> Eu acabei de ver uma pergunta interessante no Perlmonks e queria 
> reproduzir-la. O cara mostrou dois código que de vista ambos deveriam 
> funciar, mas não foi o caso, vejam só:
>  
> %hash =  map { $_, "$var/$_" } @array;   # Works great
perl -MData::Dumper -e '$var = "X"; %hash =  map { $_, "$var/$_" } 
"a".."h"; print Dumper( \%hash ), "\n"; '
$VAR1 = {
           'e' => 'X/e',
           'a' => 'X/a',
           'd' => 'X/d',
           'c' => 'X/c',
           'h' => 'X/h',
           'b' => 'X/b',
           'g' => 'X/g',
           'f' => 'X/f'
         };

> %hash =  map { "$var/$_", $_ } @array;   # Syntax Error!

perl -MData::Dumper -e '$var = "X"; %hash =  %hash =  map { "$var/$_", 
$_ } "a".."h"; print Dumper( \%hash ), "\n"; '
syntax error at -e line 1, near "} "a""
Execution of -e aborted due to compilation errors.

> A explicação é que '{' pode inicar tanto um hash como um bloco, sendo 
> assim a '{' pode ser utilizada tanto para iniciar um bloco como para 
> LIST, expressão. Como o Perl não olha a sentença inteira (na verdade eu 
> acho que nenhuma linguagem de programação faz, elas compilam do início 
> para o final e da esquerda para a direita - linearmente...), o map tem 
> que adivinhar o que é desejado. Sendo assim é só utilizar a velha regra 
> de matemática de explicitar o que você quer fazer primeiro com '()'. 
> (mais informação : perldoc -f map )

   Correto! Perfeito!

> A solução para o código com erro de sintaxe é :

   Solução? Vamos ver isso mais de perto...

> %hash =  map { ( "$var/$_", $_ ) } @array; ou
Reproduzi assim:
perl -MData::Dumper -e '$var = "X"; %h = map { ( "$var/$_", $_ ) } 
"a".."h"; print Dumper( \%h ), "\n";'

E obtive:
$VAR1 = {
           'X/f' => 'f',
           'X/e' => 'e',
           'X/b' => 'b',
           'X/d' => 'd',
           'X/h' => 'h',
           'X/c' => 'c',
           'X/a' => 'a',
           'X/g' => 'g'
         };


> %hash =  map +{ "$var/$_", $_ } @array;

Notem que aqui existe um erro de sintaxe: deveria haver uma ',' depois 
de '}' e antes de '@', na linha acima...

Reproduzi assim:
perl -MData::Dumper -e '$var = "X"; %h = map +{ "$var/$_", $_ }, 
"a".."h"; print Dumper( \%h ), "\n";'

E obtive:
$VAR1 = {
           'HASH(0x81bae74)' => {
                                  'X/d' => 'd'
                                },
           'HASH(0x813eb9c)' => {
                                  'X/h' => 'h'
                                },
           'HASH(0x81baee0)' => {
                                  'X/f' => 'f'
                                },
           'HASH(0x813eab8)' => {
                                  'X/b' => 'b'
                                }
         };

   Desnecessário dizer que os códigos produzem coisas diferentes, como 
era de se esperar... ;-)

   A solução esperada para o problema (que envolve conhecer realmente o 
parser do Perl) é acrescentar um '+' antes da string, dentro das chaves, 
assim:

perl -MData::Dumper -e '$var = "X"; %hash =  %hash =  map { +"$var/$_", 
$_ } "a".."h"; print Dumper( \%hash ), "\n"; '
$VAR1 = {
           'X/f' => 'f',
           'X/e' => 'e',
           'X/b' => 'b',
           'X/d' => 'd',
           'X/h' => 'h',
           'X/c' => 'c',
           'X/g' => 'g',
           'X/a' => 'a'
         };

   Desta forma, você obtém o resultado desejado, usando a sintaxe correta.

> Olhando o problema me lembrei de uma discussão que tivemos em um dos 
> 'social meet' sobre a sintaxe do Perl, o Luis (monsieur champs) diz que 
> ela é maravilhosa (e nem aceita discutição... é um ditador em pessoa 
> :-), mas outros (como eu) acha que ela pode levar a confusão 
> (principalmente para o iniciantes), como esta.

   Eu realmente dissse que a sintaxe do Perl é maravilhosa. Mas não 
aceito que se considere a palavra "maravilhosa" semânticamente 
equivalente à palavra "didática": exatamente como os códigos 
apresentados pelo Solli, acima, as palavras dizem coisas diferentes, a 
pesar de "se parecerem muito"... (notem a ironia carregada ;-)

   <funny>
     <troll>
       Se alguém aqui está procurando uma linguagem "didática",
       melhor tentar com pascal... :-P Perl não foi projetada
       para ser "didática", mas sim "eclética". Você pode até
       ser "didático" em perl, mas apenas por que você quer.
     </troll>
   </funny>

> Isto só vem enfatizar a máxima do Perl, "Sempre existe mais de uma 
> maneira de fazer a mesma coisa".

   Perl garante mais de uma forma de fazer a mesma coisa para fazer 
coisas iguais de jeitos diferentes... você tentou fazer coisas 
diferentes usando jeitos iguais... tem coisa estranha aqui... :-)

   Foi divertido!
   Vamos conversar mais disso no próximo social meeting?
   []'Z!
-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
   Luis Campos de Carvalho is BSc in Comp Science,
   PerlMonk [SiteDocClan], Cascavel-pm Moderator,
   Unix Sys Admin && Certified Oracle DBA
   http://br.geocities.com/monsieur_champs/
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=




Mais detalhes sobre a lista de discussão Cascavel-pm