[Rio-pm] Comparação de arquivos

Bruno Buss bruno.buss em gmail.com
Quarta Novembro 21 08:21:18 PST 2012


breno++

2012/11/21 breno <breno em rio.pm.org>

> Oi Aureliano,
>
> acho que o que o Tiago quis dizer é "o que deveria estar acontecendo
> mas não está, e o que está acontecendo em vez disso?"
>
> Assumindo que não há problema na lógica e o que está tentando resolver
> são os warnings que colou no final do paste, a resposta está na
> recomendação número 5 abaixo.
>
> Agora, algumas dicas gerais sobre o código que você colou:
>
> 1) a solução canônica para manipulação de listas são os módulos
> List::Util, List::MoreUtils e List::AllUtils (que agrega as funções de
> ambos). No List::MoreUtils (e, consequentemente, no List::AllUtils) há
> a função uniq() que faz o mesmo que o Array::Uniq. Então, a menos que
> você tenha um excelente motivo para usar o Array::Uniq, recomendo
> trocar para o List::MoreUtils.
>
>
> 2) Evite open() com apenas dois argumentos. Evite open() com barewords
> em vez de variáveis. Por mais que você saiba o que está fazendo,
> procure sempre manter a sintaxe:
>
> open my $fh, '<', $nome_do_arquivo
>    or die "erro abrindo arquivo $nome_do_arquivo para leitura: $!";
>
> para leitura, ou:
>
> open my $fh, '>' $nome_do_arquivo
>   or die "erro abrindo arquivo $nome_do_arquivo para escrita: $!";
>
> Se quiser omitir o "or die..." basta colocar "use autodie;" no início
> do seu programa.
>
> Mais ainda, pode usar módulos como Path::Class que já manipulam o
> arquivo para você:
>
>   use Path::Class;
>
>   my $fh = file( 'meuarquivo.txt' )->openr();  # ou openw() para escrever
>
> Veja mais detalhes em https://metacpan.org/module/Path::Class::File
>
>
> 3) Ao colar um exemplo, certifique-se que ele está limpo. A linha 75,
> por exemplo, tenta abrir um arquivo para escrita:
>
> open SL, ">:raw", "sl.txt" or die $!;
>
> mas não faz nada com ele.
>
>
> 4) Evite usar termos como new() e $self quando seu código não for
> orientado a objetos. Essas não são palavras reservadas em Perl, mas
> convenciona-se que new() constrói objetos e $self os referencia. Usar
> esses nomes com outros objetivos confunde :)
>
>
> 5) Evite "ações à distância"
> (
> https://en.wikipedia.org/wiki/Action_at_a_distance_%28computer_programming%29
> ).
> A variável especial $_, por exemplo, é global quando seu código espera
> que ela seja local. Repare que você está consumindo seus dados usando
> $_ implicitamente em 3 momentos distintos e concorrentes:
>
>   foreach (@in) {    # $_ definido como o valor atual em @in
>
>      print find_m($_), find_h($_);
>   }
>
>   sub find_m {
>      my $self = shift;
>      while (<INM2>) {  # $_ redefinido, agora para a linha atual
>         ...
>      }
>      # ao final do bloco, $_ estará como undef (pois o arquivo acabou)
>   }
>
> idem para a sub find_h.
>
> A solução? Bom, a partir do Perl 5.10 (lançado a quase 5 anos atrás) é
> possível usar uma versão léxica do $_ ao declará-lo no bloco com 'my'.
> É possível também restaurar o valor global de $_ no escopo atual
> usando 'our $_', mas não é isso o que você quer. Para deixar seu
> código claro e evitar efeitos colaterais, sugiro sempre "dar nomes aos
> bois" e nomear suas variáveis de loop. Por exemplo, trocar:
>
>    foreach (@in)
>
> por
>
>   foreach my $elemento (@in)
>
> já teria resolvido seu problema (assumindo, claro, que agora você
> estaria passando "$elemento" para as funções, em vez de "$_").
> Recomendo mudar também no while() dentro das subs.
>
> Outro problema de 'action at a distance' no seu código, menos grave
> mas ainda assim importante, é que você está usando nas funções find_m
> e find_h handles abertos em outro bloco, referenciados pela mesma
> bareword. Fiquei sem entender se a sua lógica considera o consumo
> linear do arquivo (para cada ocorrencia em @in, os arquivos hybrid.txt
> e miranda.txt estarão mais próximos do final) ou se isso é um bug.
>
>
> 6) Não utilize 'our' quando não precisar - e você não precisa nesse
> exemplo. Para saber mais sobre origem e diferenças entre my, our,
> local e etc, recomendo a palestra do Util =>
> http://youtu.be/Ton-5tvDQiE
>
>
> 7) Não utilize variáveis globais quando não precisar - e você não
> precisa nesse exemplo.
>
>
> 8) Não agrupe elementos em expressões regulares se não for utilizar.
> Nas regexes das subs parsin_m() e find_m() você tem dois grupos
> (parenteses () dentro da regex) e só usa o $1.
>
>
> 9) Não manipule $/ diretamente. Se realmente precisar, faça "local $/
> = ..." dentro do bloco.
>
>
> 10) Se as saídas de 'hybrid' e 'miranda' são sempre nesse formato,
> crie um parser separadamente para elas e utilize em seu código. Deixa
> tudo mais limpo e de quebra você ainda pode colocar no CPAN e ajudar
> outras pessoas :)
>
>
> 11) No seu código você abre os arquivos 'hybrid.txt' e 'miranda.txt'
> duas vezes para leitura. Isso normalmente significa que você poderia
> ter colocado tudo numa estrutura de fácil acesso e manipulação, e lido
> o arquivo apenas uma vez (operações de E/S costumam ser bem mais
> pesadas do que manipulação em memória). Dica: sempre que tiver mais de
> um while() ou foreach() varrendo a mesma estrutura para ler dados, é
> bem possível que você possa otimizar e deixar mais claro seu algoritmo
> fazendo a varredura apenas uma vez.
>
>
> 12) Sempre que o seu programa estiver fazendo algo estranho, tente
> diminuir ao máximo a superfície de erro, e inspecionar o valor das
> variáveis. No seu caso, por exemplo, o interpretador disse que o
> problema estava quando a sua linha de print chamava as funções:
>
>    print OUT ("#" x 20 , find_m($_) , "\n" , find_h($_) , "#" x 20 , "\n");
>
> então o primeiro passo seria desmembrar, retirando tudo que é inútil (
> '#' x 20 ) e colocando cada chamada em uma linha diferente, para
> tentar isolar o erro. Outra, claro, é imprimir direto na tela em vez
> de em arquivo:
>
>    print find_m($_);
>    print "\n";
>    print find_h($_);
>
> Se a sua variável for uma estrutura maior em vez de apenas uma string,
> soluções como o Data::Printer podem te ajudar também.
>
>
> Espero ter ajudado!
>
> []s
>
> -b
> _______________________________________________
> Rio-pm mailing list
> Rio-pm em pm.org
> http://mail.pm.org/mailman/listinfo/rio-pm
>



-- 
Bruno C. Buss
http://www.brunobuss.net
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/rio-pm/attachments/20121121/d37b35f9/attachment-0001.html>


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