当前位置: 首页 > 知识库问答 >
问题:

Perl 6中嵌套映射和非嵌套映射的上下文有什么区别?

穆轶
2023-03-14

我有这段代码。第一个非嵌套的映射输出了一些东西,而嵌套的映射没有。我想我理解为什么第二个不起作用。这是一个延迟序列,Perl 6正在收集结果。那很好。但是,第一个(非嵌套的)映射不是以同样的方式懒惰吗?如果我不对映射结果做任何操作,它将如何输出任何内容?也就是说,第一个怎么懒惰?is是否会自动获取一个接收器上下文,在该上下文中,我必须显式地向嵌套的接收器提供接收器(或其他内容)?不知何故,我认为Perl 6应该能够为我解决这个问题。

my @array = (1, 2), (3, 4), ('a', 'b');

say "---On its own:";
my @item = 1, 2, 3;
@item.map: {
    say $_;
    };

say "---Inside another map:";
@array.map: {
    my @item = 1, 2, 3;
    @item.map: {
        say $_;
        }
    };

以下是输出:

---On its own:
1
2
3
---Inside another map:

这与在Perl 6中如何在“for”循环中使用“map”有关?。这一条说明了该做什么,但我更多的是问一个为什么的问题。

在这种情况下,解决方案是添加渴望接收器或分配给内部map

say "---eager:";
@array.map: {
    my @item = 1, 2, 3;
    eager @item.map: {
        say $_;
        }
    };

say "---sink:";
@array.map: {
    my @item = 1, 2, 3;
    sink @item.map: {
        say $_;
        }
    };

say "---assignment:";
@array.map: {
    my @item = 1, 2, 3;
    @ = @item.map: {
        say $_;
        }
    };

共有2个答案

呼延才俊
2023-03-14

. map基本上返回一个。Seq。发生的情况是内部映射将Seq返回到外部映射,但由于该映射的结果被沉没,它们会消失而不会被迭代

如果你说的是外部贴图,你会拉内部贴图的结果,你会看到的结果。Seq返回的内部映射:

my @array = (1, 2), (3, 4), ('a', 'b');
say "---Inside another map:";
say @array.map: {
    my @item = 1, 2, 3;
    @item.map: {
        say $_;
        }
    }
---Inside another map:
1
2
3
1
2
3
1
2
3
((True True True) (True True True) (True True True))

希望有意义:-)

另一种解决方案是向外部映射添加特定的返回值。然后内部映射将下沉,并因此进行迭代,如下所示:

my @array = (1, 2), (3, 4), ('a', 'b');
say "---Inside another map:";
say @array.map: {
    my @item = 1, 2, 3;
    @item.map: {
        say $_;
        }
    42   # make sure ^^ map is sunk
    }
---Inside another map:
1
2
3
1
2
3
1
2
3
谷梁智
2023-03-14

每个程序文件、块、子例程等的内容都是由分号分隔的语句组成的“语句列表”。记住这一点:

>

  • 沉没的语句:

    • 除了报表列表中的最终报表之外,其他所有报表都包含在内
    • 语句列表级别为3的任何循环语句(,while,etc.2),即使是最后一个循环语句
    • 程序或模块文件的顶级语句列表中的任何语句,即使它是最后一条4

    返回而不是沉没的语句:

    • 除上述情况外,报表列表中的最终报表

    下沉势力急切评价,回归没有。

    在您的例子中,第一个map语句位于语句列表的中间,因此它会下沉。

    但是嵌套的map语句是其语句列表的最终语句,因此其结果以尚未迭代的Seq形式返回。

    它的父语句map也是一个final语句,但它位于程序文件的顶级语句列表中,因此它会下沉,导致它急切地迭代由三个Seq值组成的序列。(在内部映射之前插入一条say语句,以查看此内容。)
    但这三个内部值中的每一个都不会下沉或以其他方式迭代。

    更详细地说,摘自提要04,第664行:

    在任何语句序列中,都只返回final语句的值,因此所有之前的语句都会在sink上下文中进行计算,而sink上下文会自动进行求值,以强制计算副作用。(副作用首先是执行此类语句的唯一原因,事实上,如果您在接收器上下文中做了一些“无用”的事情,Perl会警告您。)sink上下文中的循环不仅会热切地评估自身,而且可以优化循环中任何值的生成。

    语句列表的最终语句不是接收器上下文,可以返回任何值,包括延迟列表。然而,为了支持命令式程序员的期望(事实证明,我们中的绝大多数人),作为语句列表的最终语句的任何显式循环都会自动强制使用sink语义,以便循环在从块返回之前执行到完成。

    此强制接收上下文仅在语句列表级别应用于循环,即在编译单元的顶层,或直接在块中应用。将单个语句或半列表解析为参数的构造被假定为需要该语句的结果,因此即使该语句是循环,此类构造仍然是懒惰的。

    当右大括号显示为行的最后一个正确标记时,如my@a=@b.map:{$\u1}\35;空格/注释不计算在内,它也会结束当前语句,但在其他情况下,需要分号来分隔语句

    地图不算数,因为它是一个函数而不是循环关键字

    3) 意味着当循环语句出现在与直接出现在语句列表中不同的位置时,例如
    懒为^10{. say}#作为期望单个语句的关键字的参数
    (for^10{. say})#在表达式
    中,那么默认情况下它不会沉没。这就是概要引用的最后一段试图说的。

    更新:在Rakudo中似乎并不是这样,但这可能是一个错误。

    4)概要中没有提到这条规则,但这是它在Rakudo中的工作方式,我很确定这是故意的。

  •  类似资料:
    • 我用的是Protobuf 3。从文档来看,似乎无法定义嵌套贴图: 我正在尝试创建一种消息类型来表示期权链的定价信息(出价和要价)。对于那些不熟悉这些金融工具的人,基本上我有一套“到期日期(YYYYMMDD)”。在每个过期日期中,我都有一组“strikes(float number;如果需要,可以用字符串表示,我同意)”。在每次行使中,我有两个期权,一个“看跌”和一个“看涨”(这被称为期权的“右”)

    • 我尝试使用MapStruct编写映射器类,如下所示: 目前它显示了“未知属性”“customer.customerid”和“usertypes.usertype.userid”等错误。有人能帮我用MapStruct映射所有这些元素吗? 问题2:我们如何绘制跟踪图?1)customerId usertypes->user->userid 2)pdtPrice offers->OffersType->

    • 我用下面的方法尝试了嵌套映射。 我在声明“root_cause”时出错:[{“type”:“mapper_parsing_exception”,“reason”:“root映射定义有不支持的参数:[type:nested]。” 感谢您的帮助。

    • 我有一个方法可以返回相当嵌套的JSON,比如: 当我尝试使用< code>JsonSlurper将这个JSON slurp到< code>def result中时,我得到了异常: 当<code>parseText</code>执行时产生引发的异常: 有什么办法吗?

    • 我有一个dynamodb表,它的一个属性包含一个嵌套的映射,我想更新一个特定的库存项目,该项目通过一个过滤器表达式进行过滤,从而从该映射中生成一个项目。 如何编写一个更新表达式来更新位置到名称=欧宝的项目的“就位三”,标签包括“x1”(也可能是f3)?这应该只更新第一个列表元素位置属性。

    • 有人能帮忙填写上面的评论部分吗?或者是否有其他选项来映射这些对象? 编辑:我尝试了下面的解决方案,但是接口实现类本身发生了变化。