【问题标题】:Is there a straightforward way to check if something is a mixin?有没有一种简单的方法来检查某个东西是否是 mixin?
【发布时间】:2021-06-27 08:39:00
【问题描述】:

Raku mixins 有两个(或多个)性质,将多个值组合在同一个容器中,或者将值与角色组合在一起。但是,据我所知,没有一种直接的方法可以检查不是您创建的变量中的“混合性”。

这可能是个技巧

my $foo = 3 but Stringy;
say $foo.^name ~~ /\+/;# OUTPUT: «「+」␤»

但是我还缺少其他可以直接查找的属性吗?

【问题讨论】:

  • 嗨,JJ。请考虑解释您正在解决的问题是什么导致您认为解决方案能够轻松地知道某些值带有 mixin。
  • 您的“技巧”使用 mixin 内省 value。使用已绑定到变量的 mixin 内省 容器 可能是不同的咒语(例如,如果它是 Scalar,则使用 .VAR)。并且内省 变量 本身将需要另一个咒语(使用类似 .var.VAR 的东西)。

标签: mixins raku


【解决方案1】:

我认为您缺少 ^roles^parents 元方法:

my $foo = 3 but Stringy;
dd $foo.^roles;   # (Stringy, Real, Numeric)
dd $foo.^parents; # (Int,)

【讨论】:

  • 这让我走到了一半;据我所知,^roles 即使没有 mixin,也会返回两个角色。所以我仍然需要以其他方式检查是否有 mixin...
  • 那把原来混进去的角色拿出来? my $foo = 3 but Stringy; dd $foo.^roles.grep: { $_ ∉ 3.^roles }; # (Stringy,).Seq
  • 假设你得到一个变量,但你不知道混入了什么,或者即使混入了一些东西。顺便说一句,dd 不考虑混入...即将发布的问题。
  • 好吧,您也可以与.^name 联系。但是任何 mixin 也可以更改其名称,这就是为什么您在 Int 的名称中看不到 RealNumeric。另见例如我的诠释@a; dd @a.^name, @a.^roles; # "Array[Int]" (Array::Typed[Int], Positional[Int], Positional, Iterable)`.
【解决方案2】:

TL;DR我的不可靠解决方案[1]比您的不可靠解决方案更简单、更快[2] 并且应该适用于问题 Y 和问题 X[3]

sub is-mixin ($object) { $object.^is_mixin =:= 1 }
say is-mixin 3;           # False
say is-mixin 3 but 'bar'; # True

脚注

[1] “警告:[role Metamodel::Mixins] 是 Rakudo 实现的一部分,而不是语言规范的一部分。”

[2] 我没有搜索过烤肉,但可以想象在类型名称中使用 + 只是一种约定,而不是语言的一部分规范。

[3] 根据我在下面的第一条评论,我发现您的问题是XY problem 的一个例子;和/或术语混乱,每秒。这个答案的其余部分解释了我的意思。

有没有一种简单的方法来检查容器是否是 mixin?

“容器”一词在 Raku 中具有技术含义。它指的是遵循 Raku 的容器协议的值。当一个值后跟= 调用“赋值”时,容器协议适用。

您所问的似乎与这样的 容器 无关,因为它不同于 。并且有充分的理由认为这对你来说并不重要——你只感兴趣的是测试一个值是否是一个 mixin,而“容器”方面是一个红鲱鱼,要么是因为你没有意思是 Raku 中通常意义上的“容器”,或者因为容器 一个值,所以无论如何都无关紧要,所以任何用于测试值的方法都可以用于测试容器。

例如,看你的“把戏”:

my $foo = 3 but Stringy;
say $foo.^name ~~ /\+/;# OUTPUT: «「+」␤»

这个技巧与使用 Raku 中“容器”一词的正常技术使用的任何容器方面无关。如果您编写不涉及容器的以下内容,您会得到相同的结果:say (3 but Stringy).^name ~~ /\+/;# OUTPUT: «「+」␤»

因此,在我的解决方案中,我假设您只是一个 ,因为您知道最终关注点是否在容器上实际上并不重要。

如果我的假设是错误的,并且它产生了影响,我敦促你解释你正在尝试做的事情的 X 而不仅仅是 Y。

【讨论】:

    【解决方案3】:

    你的把戏让你的代码变脆,因为它不期望

    $foo.^set_name('The Spanish Inquisition');
    

    当然没有人这样做:)

    你最好还是 ask the Rakudo Metamodel:

    say $foo.^is_mixin; # OUTPUT: «1␤»
    

    需要注意的两点:

    1. is_mixin 元方法不返回 Bool
    2. name 元方法一样,它特定于 Raku 的 Rakudo 实现

    【讨论】:

    • 'The Spanish Inquisition'。这让我高兴——甚至可能触动——我! ?
    猜你喜欢
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 2017-06-21
    • 2012-03-12
    • 2011-06-20
    • 1970-01-01
    相关资源
    最近更新 更多