何时调用迭代器方法?

时间:2018-05-29 09:08:56

标签: mixins perl6

这个问题是in the same ballpark as this other on making blocks iterable,但似乎揭示了mixins的一个不同问题(或者我对语法的不同误解)。 Iterable所做的是使数据结构有效地可迭代,也就是说,您可以通过在for前面创建循环。

  

Iterable用作可以使用for构造和相关迭代构造迭代的对象的API,如超级运算符。

因此,让我们尝试将其付诸实践:

 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 :(得分:5)

我认为你不能。基本问题是&fooCallable对象)和foo()(调用Callable对象)是两个非常不同的东西。

感谢我,您尝试将method添加到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。所以这可能不是你想要的。

答案 1 :(得分:1)

  

for何时调用迭代器方法?

据我了解,如果迭代功能的(single)参数是Scalar容器,则它使用容器中的值而不调用.iterator。否则,它会在其上调用.iterator,如果它是表达式或例程调用,则首先对其进行评估。

&logger does Forable;
.say for &logger;
  

这根本行不通; say作为简单项目应用于&logger

&是一个名词标记(sigil),标记Callable本身就是一个单一的东西,一个代码块。

更具体地说,&logger绑定到Scalar容器,其类型为Callable,与$logger(带$ sigil)完全相同如果你写了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}

实际上<{1}} Callable Scalar &logger }。

&logger容器本身的类型,Scalar,如上所示。

当以变量的形式给出单个参数时,迭代功能如for查看变量,而不是变量中包含的值,以查看它是否IterableScalar不是Iterable

  

关于如何解决这个问题的任何想法?

请参阅lizmat针对一种方法的答案。