Perl 6 - 是否可以创建设置元属性的属性特征?

Perl 6 - Is it possible to create an attribute trait that set a meta-attribute?

我尝试创建属性特征。用例是在 objects-to-documents-mapping 的上下文中将 class 的某些属性标记为 "crudable",而其他则不是。

role crud {
    has Bool $.crud is default(True);
}

multi trait_mod:<is>(Attribute $a, crud, $arg) {
    $a.container.VAR does crud($arg);
}

class Foo {
    has $.bar is rw;

    # Provide an extra nested information
    has $.baz is rw is crud(True);
}

通过阅读和改编 some example code, I managed to get something that seems to do what I want. Here is a snippet with test case

当我实例化一个新的 Foo 对象并设置 $.bar 属性(is 而不是 crud)时,它看起来像这样:

.Foo @0
├ $.bar is rw = 123456789
└ $.baz is rw = .Scalar+{crud} @1
  └ $.crud +{crud} = True

据我了解,$.baz 属性得到了我所说的 元属性 ,它独立于其潜在值。

它对我来说看起来不错(如果我正确理解我在这里所做的并且我的特征使用不是肮脏的黑客)。有可能达到$foo.baz.crudTrue。虽然,我不太明白 .Scalar+{crud} 是什么意思,如果我可以在那里设置一些东西以及如何设置。

当我尝试设置 $.baz 实例属性时,返回此错误:

Cannot modify an immutable Scalar+{crud} (Scalar+{crud}.new(crud => Bool::True))
  in block <unit> at t/08-attribute-trait.t line 30

注意:这是我设法获得的最接近可行解决方案的东西。对于实例化 Foo classes.

的不同实例,我不需要不同的 crud 设置

我从来不想改变布尔值,事实上,一旦对象实例化,只是将它提供给具有 is crud 的属性。我什至没有兴趣将 TrueFalse 值作为参数传递:如果可以将布尔特征属性默认设置为 True,就足够了。虽然我没有设法做到这一点,例如:

multi trait_mod:<is>(Attribute $a, :$crud!) {
    # Something like this
    $a.container.VAR does set-crud;
}

class Foo {
    has $.bar is rw;
    has $.baz is rw is crud;
}

我是不是在尝试做一些不可能的事情?我如何调整此代码以实现此用例?

这里发生了几件事。首先,trait_mod 的签名看起来是错误的。其次,当特征的名称与现有角色的名称相同时,似乎存在不良交互。我相信这应该是 NYI 异常,但显然它要么在解析时出错,要么在尝试生成错误消息时出错。

无论如何,我想这就是你想要的:

role CRUD {};  # since CRUD is used as an acronym, I chose to use uppercase here

multi trait_mod:<is>(Attribute:D $a, :$crud!) { # note required named attribute!
    $a.^mixin: CRUD if $crud;  # mixin the CRUD role if a True value was given
}

class A {
    has $.a is crud(False);  # too bad "is !crud" is invalid syntax
    has $.b is crud;
}

say "$_.name(): { $_ ~~ CRUD }" for A.^attributes; # $!a: False, $!b: True

希望对您有所帮助。