这个问题是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
。关于如何解决这个问题的任何想法?
答案 0 :(得分:5)
我认为你不能。基本问题是&foo
(Callable
对象)和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
查看变量,而不是变量中包含的值,以查看它是否Iterable
。 Scalar
不是Iterable
。
关于如何解决这个问题的任何想法?
请参阅lizmat针对一种方法的答案。