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.crud
即True
。虽然,我不太明白 .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
的属性。我什至没有兴趣将 True
或 False
值作为参数传递:如果可以将布尔特征属性默认设置为 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
希望对您有所帮助。
我尝试创建属性特征。用例是在 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.crud
即True
。虽然,我不太明白 .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
的属性。我什至没有兴趣将 True
或 False
值作为参数传递:如果可以将布尔特征属性默认设置为 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
希望对您有所帮助。