当原始变量具有默认强制时,有没有办法访问混合组件?

问题描述

例如,在这种情况下:

my @list = (2,) but "bar";
put @list.Str «2␤»

似乎没有办法访问“bar”组件。我错过了什么吗?例如,Set

也会发生同样的情况
my @list = (2,3) but Set(4,5);
put @list.Set; # OUTPUT: «3 2␤»

解决方法

赋值是一个复制操作,所以:

my @a = something;

Array 中创建一个 @a,迭代 something,并将每个元素存储在 @a 中。如果改为使用绑定:

my @list := (2,) but "bar";
put @list.Str;

然后将带有mixin的列表绑定到符号@list上,输出为:

bar
,

TL;DR 我想我现在更接近理解你的意思了。我在这个答案的开头分享了基于这种理解的各种解决方案。 (这个答案的其余部分现在可能大部分都没有实际意义,但我把它留了下来,因为我认为它仍然有一些价值,尤其是仍然让我感到困惑的明显错误。)

我现在认为你想要的一些解决方案

role foo { method Str { 42 } }
...
say @bar.Str; # 42

适当填写 ... 的地方,例如以下之一:

  • class List2 is List does foo {}
    my @bar is List2;
    

    这是做什么的,什么时候:

    • 创建一个新的容器类型 List2,由角色 List 组成 foo

    • 永久将变量 @bar“绑定”到新容器类型的新实例。

    • 所有这些都发生在编译时

  • my @bar is List;
    @bar does foo;
    

    这是做什么的,什么时候:

    • 永久“绑定”变量 @barList 的新实例 在编译时

    • 永久foo混合到同一个 List实例在运行时。 >

  • my @bar := (1,2) but foo
    

    这是做什么的,什么时候:

    • 在编译时从文字 (List) 构造一个新的 (1,2) 实例。

    • 运行时构造一个new实例,它是从列表字面量构造的List克隆 但是混入了 foo 角色。

    • 临时将变量 @bar“绑定”到 new List / foo 对象({{1 }}).

我原来的回答

您共享的代码及其行为大多是基本的普通行为。 jnthn 的回答解释了这些基本方面。这个答案提供了更多细节,并指出了一个让我感到惊讶并且可能是错误的部分。

当原始变量有默认强制时,有没有办法访问混合组件?

我想我看到了一些出乎意料的事情,这可能就是你所说的。但我不会将其描述为“默认强制”,因为“默认”和“强制”在 Raku 中已经具有特定含义,并且与这些无关。对奇怪的行为取模,这只是 Raku 将复数值分配给复数变量的普通语义。

例如,在这种情况下:

(1,2) but foo

jnthn 的回答解释了为什么这行不通。简而言之,mixin 在复数值上,而不是在复数值内的每个元素 上,因此它不会作为赋值的一部分被复制。在开始之前,您的代码已“损坏”。

可以合理地写出这样的东西并期望它起作用:

my @list = (2,) but "bar";

第一行中的 my @list = (2,) Zbut "bar"; put @list.Str; # «bar␤» 使用 zip 语义将 Z 分布在复数 but 值中的单数元素上。只有一个元素 -- List -- 但如果有更多元素也可以使用:

2

明确第二行中发生的事情很有用。

正在对 复数 值调用 my @list = 2,3 Zbut "bar","foo"; put @list.Str; # «bar foo␤» 方法(隐式创建并绑定到 .Str 作为声明 {{1 }}).

与大多数编程语言一样,Raku 中的每个例程都可以主要根据其参数来决定要做什么。与大多数具有方法的 PL 一样,方法可能会根据其调用者的不同而做令人惊讶的不同事情。

在 Raku 中,Array 方法,当使用 复数 值/变量调用者分配一个 @list 到该复数调用者中的每个元素. (如果它的任何元素本身是另一个复数,则调用将递归地对其元素执行相同的操作。)完成后,一系列生成的单个字符串将连接在一起,每个字符串之间有一个空格。

同样的情况,例如,my @list

和以前一样,您将再次需要将 mixin 分发到第一行中的各个元素,以便有机会解决问题:

.Str

但是现在 second 行仍然无法满足您的期望:

.Str

问题是这次您要处理 Set

在复数上调用 my @list = (2,3) Zbut Set(4,5); 与在复数上调用 put @list.Set; # OUTPUT: «3 2␤» 不同。它具有完全不同的语义。它所做的是从复数值的元素集合中构造一个集合。因此:

.Set

希望到目前为止这一切都有意义。

这就是让我感到惊讶的地方。这似乎有效:

.Set

但是如果我们更改第一行,事情就不会像我预期的那样工作:

.Str

这让我很困惑。我会睡在上面。但现在看来这可能是一个错误。