Список :: Util - уменьшить - длина - кодировка - вопрос - PullRequest
2 голосов
/ 21 ноября 2010

Почему я получаю неправильный результат с первым примером уменьшения?

test.txt

__BE  
bb bbbbbbbbbbbbbbb  

aaaaaa  

test.pl

#!/usr/bin/env perl
use warnings; use 5.012;
use open ':encoding(UTF-8)';
use List::Util qw(reduce);
use Encode;

my( @list, $longest, $len );
open my $fh, '<', 'test.txt' or die $!;
    while( my $line = readline( $fh ) ) {
    chomp $line;
    push @list, split( /\s+/, $line );
    }
close $fh;

$longest = reduce{ length($a) > length($b) ? $a : $b } @list;
$len = length $longest;
say $longest; # aaaaaa
say $len;     # 6

$longest = reduce{ length(Encode::encode_utf8($a)) > length(Encode::encode_utf8($b)) ? $a : $b } @list;
$len = length(Encode::encode_utf8($longest));
say $longest;  # bbbbbbbbbbbbbbb
say $len;     # 15

$longest = $list[0];
$len = length $longest;
for my $str (@list) {
    if ( length($str) > $len ) {
        $longest = $str;
        $len = length($str);
    }
}
say $longest; # bbbbbbbbbbbbbbb
say $len;     # 15

Ответы [ 2 ]

2 голосов
/ 21 ноября 2010

AFAICS, это может быть даже ошибка в Perl ... конечно, не очевидно, что он ведет себя правильно. Я изменил первый редукции для диагностики печати, как оно идет:

#!/usr/bin/env perl
use warnings; use 5.012;
use open ':encoding(UTF-8)';
use List::Util qw(reduce);
use Encode;

my( @list, $longest, $len );
open my $fh, '<', 'test.txt' or die $!;
    while( my $line = readline( $fh ) ) {
    chomp $line;
    push @list, split( /\s+/, $line );
    }
close $fh;

$longest = reduce { say "<<$a>>/<<$b>> : ", length($a), " : ", length($b);
                    length($a) > length($b) ? $a : $b } @list;
$len = length $longest;
say $longest; # aaaaaa
say $len;     # 6

$longest = reduce { length(Encode::encode_utf8($a)) > length(Encode::encode_utf8($b)) ? $a : $b } @list;
$len = length(Encode::encode_utf8($longest));
say $longest;  # bbbbbbbbbbbbbbb
say $len;     # 15

$longest = $list[0];
$len = length $longest;
for my $str (@list) {
    if ( length($str) > $len ) {
        $longest = $str;
        $len = length($str);
    }
}
say $longest; # bbbbbbbbbbbbbbb
say $len;     # 15

При запуске на MacOS X (10.6.5) с использованием Perl 5.13.4, я получаю вывод:

<<>>/<<__BE>> : 0 : 4
<<__BE>>/<<>> : 0 : 0
<<>>/<<bb>> : 0 : 2
<<bb>>/<<bbbbbbbbbbbbbbb>> : 0 : 15
<<bbbbbbbbbbbbbbb>>/<<>> : 0 : 0
<<>>/<<aaaaaa>> : 0 : 6
aaaaaa
6
bbbbbbbbbbbbbbb
15
bbbbbbbbbbbbbbb
15

По всей видимости, первым аргументом первого сокращения всегда является строка нулевой длины, даже в тех нечетных случаях, когда она содержит некоторые данные.

Если строка 'use open ':encoding(UTF-8)';' удалена, то она ведет себя разумно.

<<>>/<<__BE>> : 0 : 4
<<__BE>>/<<>> : 4 : 0
<<__BE>>/<<bb>> : 4 : 2
<<__BE>>/<<bbbbbbbbbbbbbbb>> : 4 : 15
<<bbbbbbbbbbbbbbb>>/<<>> : 15 : 0
<<bbbbbbbbbbbbbbb>>/<<aaaaaa>> : 15 : 6
bbbbbbbbbbbbbbb
15
bbbbbbbbbbbbbbb
15
bbbbbbbbbbbbbbb
15

Это может указывать на то, что ошибка находится где-то во взаимодействии файлового ввода-вывода, кодировки UTF-8 и List :: Util. С другой стороны, это может быть где-то более неясным. Но у меня сложилось впечатление, что у вас есть контрольный пример, который можно воспроизвести и о котором можно сообщить как о возможной ошибке где-то в Perl и его основных модулях.

1 голос
/ 21 ноября 2010

Я сообщил об этом как об ошибке в List :: Util после попытки изменить эту программу.

...