Когда вызывается метод итератора? - PullRequest
0 голосов
/ 29 мая 2018

Этот вопрос находится на том же уровне, что и этот при создании блоков, повторяемых , но, похоже, обнаруживает другую проблему с миксинами (или другое неправильное понимание синтаксиса с моей стороны).Iterable делает эффективную итерацию структуры данных, т. Е. Вы можете создавать циклы, предшествуя ей for.

Итерируемый служит API дляобъекты, которые можно итерировать с помощью конструкции for и связанных с ней итераций, например, гипероператоры.

Итак, давайте попробуем применить это на практике:

 my &logger = -> $event  {
    state %store;
    if ( $event ) {
        %store{ DateTime.new( now ) } = $event;
    } else {
        %store;
    }
}

role Forable does Iterable {
    method iterator(&self:) {
        self( Nil );
    }
}

logger( "One" );
logger( "Two" );

&logger does Forable;

.say for &logger;

Это просто не работает;say применяется к &logger как простой элемент.Тем не менее, это работает, если мы изменим это последнее предложение на:

.say for &logger.iterator;

Что, как я полагаю, указывает на то, что роль действительно работает и смешана. Поскольку тип для &logger равен Block+{Forable}, возможно,это не работает, если Iterable не смешивается напрямую.Фактически, удаление does Iterable из объявления Forable никак не влияет на это.Давайте попробуем тогда это:

&logger does (Iterable,Forable);

Теперь тип &logger раскрывается как Block+{Iterable,Forable}, но все равно не радость.iterator должен быть вызван напрямую.Есть идеи, как это решить?

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Когда for вызывает метод итератора?

Как я понимаю, если ( single ) аргумент функции итерации является Scalarконтейнера, то он использует значение в контейнере и не вызывает .iterator.В противном случае он вызывает .iterator для него, сначала оценивая его, если это выражение или обычный вызов.


&logger does Forable;
.say for &logger;

Это просто не работает;say применяется к &logger как простой элемент.

* & - это маркер существительного (сигил), обозначающий Callable, который по своей сути является одной вещью, единым блокомcode.

В частности, &logger привязан к контейнеру Scalar, тип которого Callable, точно такой же, как $logger (с символом $), если бы вы написали my Callable $logger:

say .WHAT, .VAR, .VAR.WHAT, .VAR.of
for my &logger, my Callable $logger

отображает:

(Callable)Callable(Scalar)(Callable)
(Callable)Callable(Scalar)(Callable)

Поскольку тип для &logger равен Block+{Forable}

Это на самом деле типCallable, который содержится в Scalar контейнере, который связан с &logger.

Это не тип самого контейнера &logger,это Scalar, как показано выше.

При задании одного аргумента в форме переменной итерационные функции, такие как for, смотрят на переменную, а не на значение, содержащееся в переменной, чтобы увидетьесли это Iterable.A Scalar - это не Iterable.

Есть идеи, как это решить?

См. Ответ lizmat для одного подхода.

0 голосов
/ 29 мая 2018

Не думаю, что ты можешь.Основная проблема в том, что &foo (объект Callable) и foo() (вызов объекта Callable) - это две совершенно разные вещи.

Мне кажется, вы пытаетесь добавить *От 1007 * до class, но вы работаете с Sub.

Вам необходимо смешать метод iterator с возвращаемым значением logger.Поскольку я не совсем понимаю, чего вы пытаетесь достичь, трудно ответить на вопрос.

Глядя на результат , которого вы, очевидно, хотите достичь, я придумал это:

my %store;
multi sub logger() {
    %store
}
multi sub logger($event) {
    %store{ DateTime.new( now ) } = $event;
}

logger( "One" );
logger( "Two" );

.say for logger;

Но это совсем не использует role с.Так что это может быть не то, что вы собираетесь.

...