在 'does' 位置的 class 中从 AT-POS 方法(而不是 Proxy 实例)返回 'raw' 标量容器?
Returning a 'raw' scalar container from AT-POS method (rather than a Proxy instance) in a class that 'does' Positional?
我正在尝试实现一个 class 'does' Positional
也允许我通过分配给结果 return 来更新它的值 returned AT-POS
方法。最终,我能够编造出以下按预期工作的 class:
class Test does Positional
{
has $.slot_1 is rw = 12;
has $.slot_2 is rw = 24;
method AT-POS(\position)
{
my $t = self;
return-rw Proxy.new:
FETCH => method ()
{
position % 2 ?? $t.slot_1 !! $t.slot_2
},
STORE => method ($v)
{
if position % 2
{
$t.slot_1 = $v
}
else
{
$t.slot_2 = $v
}
}
}
}
my $test = Test.new;
die unless $test[2] == 24;
die unless $test[5] == 12;
$test[7] = 120;
die unless $test[2] == 24;
die unless $test[5] == 120;
$test[10] = 240;
die unless $test[2] == 240;
die unless $test[5] == 120;
是否有可能以某种方式(并且:简单地)return 容器 绑定到 $!slot_1
(或 $!slot_2
) Test
class 实施?
在我发现 Proxy
实例的使用之前,我尝试 return
(和 return-rw
)表达式 position % 2 ?? $!slot_1.VAR !! $!slot_2.VAR
的结果,因为我印象中VAR
方法让我可以访问底层容器,希望我可以简单地 return
它。那并没有真正起作用,我还不明白为什么:我怀疑它以某种方式被强制恢复为某个值?
换句话说:在这种特殊情况下是否可以简化我的 AT-POS
实施?
谢谢,
此致,
雷蒙.
假设您不想要“slot_1”和“slot_2”的访问器,如果我理解正确的话,这将是我的执行。我不会将其称为 Test
class,因为那样会干扰用于测试的 Test
class。
class Foo {
has @elements = 24, 12;
method AT-POS(Int:D $pos) is raw {
@elements[$pos % 2]
}
}
my $f = Foo.new;
say $f[2]; # 24
say $f[5]; # 12
$f[2] = 666;
say $f[4]; # 666
请注意,数组中的默认值已更改顺序,这是为了使 AT-POS
中的算法保持简单。
还要注意 AT-POS
方法定义中的 is raw
:它将确保返回值时不会发生去容器化。这允许您只分配给任何 $f[2]
returns.
希望这是有道理的!
此外:您可能会对 Array::Agnostic 模块感兴趣,可以直接使用,也可以用作灵感来源。
首先,如果您不打算在对象外部使用属性,则没有理由将它们声明为 public,尤其是 rw
.
class Foo {
has $!odd = 12;
has $!even = 24;
…
}
您也可以直接从方法中 return 标量容器。您应该将方法声明为 rw
或 raw
。 (raw
不保证它是可写的。)
class Foo {
has $!odd = 12;
has $!even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
# we actually get the Scalar container given to us
say Foo.new[10].VAR.name; # $!even
请注意,即使您将属性声明为 public,它们仍然具有私有名称。私有属性始终是 rw
,即使未 public 声明为 rw
。
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
如果您要使用代理,我会考虑将公共代码移到它之外。
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
# no need to write this twice
my $alias := (position % 2 ?? $!odd !! $!even);
Proxy.new:
FETCH => method () { $alias },
STORE => method ($new-value) { $alias = $new-value }
}
}
当然 ?? !!
代码是该模块的核心功能,因此将它放入一个方法中是有意义的,这样您就不会在整个 class。在这种情况下,我将其设为私有方法。
class Foo {
has $.odd = 12;
has $.even = 24;
# has to be either `raw` or `rw`
# it is debatable of which is better here
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
my $alias := self!attr(position);
Proxy.new:
FETCH => -> $ { $alias },
STORE => -> $, $new-value { $alias = $new-value }
}
}
同样,没有太多理由使用代理。
class Foo {
has $.odd = 12;
has $.even = 24;
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
self!attr(position);
}
}
您可以使用索引操作代替 ?? !!
。
method !attr(\position) is raw {
($!even,$!odd)[position % 2]
}
这将允许三元数据结构。
method !attr(\position) is raw {
($!mod0,$!mod1,$!mod2)[position % 3]
}
无需编写您所做的 if
语句,因为 Raku 通常传递标量容器而不是值。
(position % 2 ?? $t.slot_1 !! $t.slot_2) = $v;
我正在尝试实现一个 class 'does' Positional
也允许我通过分配给结果 return 来更新它的值 returned AT-POS
方法。最终,我能够编造出以下按预期工作的 class:
class Test does Positional
{
has $.slot_1 is rw = 12;
has $.slot_2 is rw = 24;
method AT-POS(\position)
{
my $t = self;
return-rw Proxy.new:
FETCH => method ()
{
position % 2 ?? $t.slot_1 !! $t.slot_2
},
STORE => method ($v)
{
if position % 2
{
$t.slot_1 = $v
}
else
{
$t.slot_2 = $v
}
}
}
}
my $test = Test.new;
die unless $test[2] == 24;
die unless $test[5] == 12;
$test[7] = 120;
die unless $test[2] == 24;
die unless $test[5] == 120;
$test[10] = 240;
die unless $test[2] == 240;
die unless $test[5] == 120;
是否有可能以某种方式(并且:简单地)return 容器 绑定到 $!slot_1
(或 $!slot_2
) Test
class 实施?
在我发现 Proxy
实例的使用之前,我尝试 return
(和 return-rw
)表达式 position % 2 ?? $!slot_1.VAR !! $!slot_2.VAR
的结果,因为我印象中VAR
方法让我可以访问底层容器,希望我可以简单地 return
它。那并没有真正起作用,我还不明白为什么:我怀疑它以某种方式被强制恢复为某个值?
换句话说:在这种特殊情况下是否可以简化我的 AT-POS
实施?
谢谢,
此致,
雷蒙.
假设您不想要“slot_1”和“slot_2”的访问器,如果我理解正确的话,这将是我的执行。我不会将其称为 Test
class,因为那样会干扰用于测试的 Test
class。
class Foo {
has @elements = 24, 12;
method AT-POS(Int:D $pos) is raw {
@elements[$pos % 2]
}
}
my $f = Foo.new;
say $f[2]; # 24
say $f[5]; # 12
$f[2] = 666;
say $f[4]; # 666
请注意,数组中的默认值已更改顺序,这是为了使 AT-POS
中的算法保持简单。
还要注意 AT-POS
方法定义中的 is raw
:它将确保返回值时不会发生去容器化。这允许您只分配给任何 $f[2]
returns.
希望这是有道理的!
此外:您可能会对 Array::Agnostic 模块感兴趣,可以直接使用,也可以用作灵感来源。
首先,如果您不打算在对象外部使用属性,则没有理由将它们声明为 public,尤其是 rw
.
class Foo {
has $!odd = 12;
has $!even = 24;
…
}
您也可以直接从方法中 return 标量容器。您应该将方法声明为 rw
或 raw
。 (raw
不保证它是可写的。)
class Foo {
has $!odd = 12;
has $!even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
# we actually get the Scalar container given to us
say Foo.new[10].VAR.name; # $!even
请注意,即使您将属性声明为 public,它们仍然具有私有名称。私有属性始终是 rw
,即使未 public 声明为 rw
。
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
如果您要使用代理,我会考虑将公共代码移到它之外。
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
# no need to write this twice
my $alias := (position % 2 ?? $!odd !! $!even);
Proxy.new:
FETCH => method () { $alias },
STORE => method ($new-value) { $alias = $new-value }
}
}
当然 ?? !!
代码是该模块的核心功能,因此将它放入一个方法中是有意义的,这样您就不会在整个 class。在这种情况下,我将其设为私有方法。
class Foo {
has $.odd = 12;
has $.even = 24;
# has to be either `raw` or `rw`
# it is debatable of which is better here
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
my $alias := self!attr(position);
Proxy.new:
FETCH => -> $ { $alias },
STORE => -> $, $new-value { $alias = $new-value }
}
}
同样,没有太多理由使用代理。
class Foo {
has $.odd = 12;
has $.even = 24;
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
self!attr(position);
}
}
您可以使用索引操作代替 ?? !!
。
method !attr(\position) is raw {
($!even,$!odd)[position % 2]
}
这将允许三元数据结构。
method !attr(\position) is raw {
($!mod0,$!mod1,$!mod2)[position % 3]
}
无需编写您所做的 if
语句,因为 Raku 通常传递标量容器而不是值。
(position % 2 ?? $t.slot_1 !! $t.slot_2) = $v;