Использование неинициализированного значения типа Any в числовом c контексте raku. - PullRequest
6 голосов
/ 11 января 2020

Я сталкивался с вопросом программирования на reddit (посмотрите ссылку на вопрос)

Это было одно из решений Python:

s="112213"
k=2
result=0
for i in range(len(s)):
    num_seen = 0
    window = {}
    for ind in range(i, len(s)):
        if not s[ind] in window:
            num_seen += 1  
            window[s[ind]] = 1
        else: 
            window[s[ind]] += 1 
        if   window[s[ind]] == k:
            num_seen -= 1
            if num_seen == 0:
                result +=1
        elif window[s[ind]] > k:
            break
print(result)

Я пытался перенести это решение в Raku, и вот мой код:

my @s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^@s {
    my $seen = 0;
    my %window;
    for @s[$_..*] {
    if $^a == %window.keys.none {
        $seen++;
        %window{$^a} = 1;}
    else {  
        %window{$^a} += 1;}
    if %window{$^a} == $k {
        $seen--;
        if $seen == 0 {
        $res++;} }
    elsif %window{$^a} > $k {
        last;}}}
say $res;

Выдает эту ошибку:

Use of an uninitialized value of type Any in a numeric context in a block at ... line 13

Как это исправить?

Ответы [ 2 ]

7 голосов
/ 11 января 2020

Я не чувствую, что это MRE . Слишком много проблем, чтобы я мог в них разобраться. Вместо этого я начал с оригинального Python и перевел это. Я добавлю несколько комментариев:

my \s="112213" .comb;      # .comb to simulate Python string[n] indexing.
my \k=2;
my $result=0;              # result is mutated so give it a sigil
for ^s -> \i {             # don't use $^foo vars with for loops 
    my $num_seen = 0;
    my \window = {}
    for i..s-1 -> \ind { 
        if s[ind] == window.keys.none {   # usefully indent code! 
            $num_seen += 1;  
            window{s[ind]} = 1
        } else {
            window{s[ind]} += 1
        }
        if window{s[ind]} == k {
            $num_seen -= 1;
            if $num_seen == 0 {
                $result +=1
            }
        } elsif window{s[ind]} > k {
            last
        }
    }
}
print($result)

отображает 4.

Я не говорю, что это хорошее решение в Раку. Это просто относительно механический перевод. Надеюсь, это полезно.

4 голосов
/ 11 января 2020

Как обычно, ответ @raiph правильный. Я просто хочу внести минимальные изменения в вашу программу, чтобы все было правильно. В этом случае просто добавьте индексы в оба цикла, чтобы сделать вещи более понятными. Вы использовали контекстную переменную $ _ в первом и $ ^ a во втором (внутреннем), и это становилось излишне запутанным.

my @s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^@s -> $i {
    my $seen = 0;
    my %window;
    for @s[$i..*] -> $c {
    if $c == %window.keys.none {
            $seen++;
            %window{$c} = 1;
    } else {  
            %window{$c} += 1;
    }
    if %window{$c} == $k {
            $seen--;
            if $seen == 0 {
        $res++;
        }
    } elsif %window{$c} > $k {
            last;
    }
    }
}
say $res;

Как видите, помимо попытки сделать отступ немного точнее, единственное дополнительное - это добавить -> $i и -> $c, чтобы циклы были проиндексированы, а затем использовать их там, где вы использовали неявные переменные.

...