Использование позиционных параметров al oop внутри внутреннего l oop в Raku - PullRequest
5 голосов
/ 07 января 2020

Вот код:

my @s=<a b c d>;
for @s.kv {
    for ($^k ... @s.elems) {
        printf("%s ", $^v);
    }
    printf("\n");
}

Ожидаемый результат:

# a b c d
# b c d
# c d
# d

Но он выдает эту ошибку (возможно, среди прочих)

key 0, val 1 Too few positionals passed; expected 2 arguments but got 1

Это похоже, что позиционные переменные основных l oop $^k и $^v не могут использоваться внутри внутреннего l oop. Как это исправить? Спасибо. Обновление: опечатка внутри l oop исправлено

Ответы [ 2 ]

6 голосов
/ 07 января 2020

Ответ Скимона Проктора по существу правильный, но я постараюсь объяснить, почему ваш пример не работает. Для начала kv возвращает «чередующуюся последовательность индексов и значений», так что:

my @s=<a b c d>;
.say for @s.kv;

печатает

0
a
1
b
2
c
3
d

По сути, вы делая один оборот l oop для каждого значения ключа и . Группировка их по парам с помощью rotor может быть ближе к тому, что вы ищете:

.say for @s.kv.rotor(2)

, который вернет:

(0 a)
(1 b)
(2 c)
(3 d)

Так как с этим мы получили пару значений с индексом, мы можем сделать ...

my @s=<a b c d>;
for @s.kv.rotor(2) -> ($k, $) {
    "{@s[$_]} ".print for ($k..^@s.elems);
    printf("\n");
}

Обратите внимание, что была также ошибка во внутренней l oop, чей диапазон вышел за пределы фактических индексов в @s , Но, опять же, ответ Шимона, который использует карты, намного короче, идиоматический c и прямой. Это просто вид вашей оригинальной программы. На самом деле мы отбрасываем значения, так что на самом деле это будет:

my @s=<a b c d>;
for @s.keys -> $k {
    "{@s[$_]} ".print for ($k..^@s.elems);
    printf("\n");
}

Не нужно вообще использовать kv, а просто обойтись с помощью клавиш .

6 голосов
/ 07 января 2020

Так что для того, что вы хотите сделать, я бы подошел к этому так:

my @s = <a b c d>;
for ^@s.elems -> $start-index {
    for @s[$start-index..*] -> $value {
        printf("%s ", $value );
    }
    print("\n");
}

Хотя на самом деле я бы сделал это.

my @s = <a b c d>;
(^@s.elems).map( { @s[$_..*].join(" ").say } )

Получите диапазон от 0 до количество элементов в массиве. Затем отрежьте оттуда до конца для каждого, объедините пробелы и скажите.

Замечание о таких переменных, как $^k, они ограничены только текущим блоком (следовательно, почему вышеприведенный код не работает). Обычно вы действительно хотите использовать их в map, grep или других подобных вещах. Там, где это возможно, я бы всегда советовал присваивать имена вашим переменным, поэтому они также ограничиваются внутренними блоками

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...