【问题标题】:When does for call the iterator method?for 什么时候调用迭代器方法?
【发布时间】:2018-11-07 21:07:15
【问题描述】:

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

Iterable 用作对象的 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,它可能不起作用。事实上,从Forable 声明中删除does Iterable 不会以任何方式影响它。让我们试试这个:

&logger does (Iterable,Forable);

现在&logger的类型显示为Block+{Iterable,Forable},但仍然没有喜悦。 iterator 必须直接调用。关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: mixins raku


    【解决方案1】:

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

    在我看来,您正在尝试将 method 添加到 class,但您正在使用 Sub

    你需要在logger的返回值上混入iterator方法。由于我不太了解您要达到的目标,因此很难回答这个问题。

    看着你显然想要实现的结果,我想出了这个:

    my %store;
    multi sub logger() {
        %store
    }
    multi sub logger($event) {
        %store{ DateTime.new( now ) } = $event;
    }
    
    logger( "One" );
    logger( "Two" );
    
    .say for logger;
    

    但这根本不使用roles。所以这可能不是你想要的。

    【讨论】:

    • Callable 是一个角色。 SubRoutineBlockCode 是类。 Callable 角色的目的是将某些东西标记为可调用(并混入一些实用方法)。您不能将Callable 角色添加到一个类中并拥有可以执行的东西。
    【解决方案2】:

    for什么时候调用迭代器方法?

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


    &logger does Forable;
    .say for &logger;
    

    这根本行不通; say 被应用到 &logger 作为一个简单的项目。

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

    更具体地说,&logger 绑定到类型为CallableScalar 容器,如果您写my Callable $logger,则与$logger(带有$ sigil)完全相同:

    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 的类型,它包含在绑定到&loggerScalar 容器中。

    不是&logger容器本身的类型,是Scalar,如上图。

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

    你知道如何解决这个问题吗?

    查看 lizmat 对一种方法的回答。

    【讨论】:

    • 最初,我想说明的是如何将角色添加到变量中。您的回答为我的一个问题提供了答案,但在这种情况下,记录器不是可迭代的,而是返回一个可迭代的。这有点回答第二个问题:当有效提供的变量有效地可迭代时,调用迭代器(在这种情况下,在哈希上)。我想我得从那里拿走它。非常感谢。
    • "将角色添加到变量中。"。正如您和I confirmed 所发现的,如果您将任何角色添加到Scalar 容器,它就会停止工作。
    猜你喜欢
    • 2016-01-11
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2015-07-13
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多