breno++ 2012/11/21 breno <br...@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@pm.org > http://mail.pm.org/mailman/listinfo/rio-pm > -- Bruno C. Buss http://www.brunobuss.net
_______________________________________________ Rio-pm mailing list Rio-pm@pm.org http://mail.pm.org/mailman/listinfo/rio-pm