代理的多方法
Multimethod for Proxy
在使用 Proxy 时,是否可以将 multidispatch 用于 store 方法?在下面的最小示例中,存储 Int
时调用代码
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE( method (Int $i) { $bar = $i } )
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3"; # error, need to pass an Int
但是如果给定 Str
,我想以不同的方式处理 STORE
。我发现的解决方法(除了使用 given
/where
执行 mega 方法外,是在块内创建一个 multi sub
,然后 return 子(因为multi method
不能用 &foo
) 引用,第一个虚拟参数是:
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE(
do {
multi sub xyzzy ($, Int $i) { $bar = $i }
multi sub xyzzy ($, Str $i) { $bar = +$i + 1}
&xyzzy
}
)
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3";
say $foo; # 4
有没有更好的方法来做到这一点(主要是为了代码清晰使用 method
因为 sub
感觉......误导)?
关于误导:FETCH
和 STORE
值预期 Callables
,可能是 method
或 sub
。
回到问题,没有直接的方法,但是有更好的间接方法,可能更清楚。您可以先设置 multi sub
,然后将 proto
作为参数传递:
proto sub store(|) {*}
multi sub store(\self, Int) { say "Int" }
multi sub store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str
如果你想让代码更短,但可能更难理解,你可以去掉 proto
(因为它会自动为你生成)和 sub
multi
(因为你可以):
multi store(\self, Int) { say "Int" }
multi store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str
在使用 Proxy 时,是否可以将 multidispatch 用于 store 方法?在下面的最小示例中,存储 Int
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE( method (Int $i) { $bar = $i } )
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3"; # error, need to pass an Int
但是如果给定 Str
,我想以不同的方式处理 STORE
。我发现的解决方法(除了使用 given
/where
执行 mega 方法外,是在块内创建一个 multi sub
,然后 return 子(因为multi method
不能用 &foo
) 引用,第一个虚拟参数是:
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE(
do {
multi sub xyzzy ($, Int $i) { $bar = $i }
multi sub xyzzy ($, Str $i) { $bar = +$i + 1}
&xyzzy
}
)
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3";
say $foo; # 4
有没有更好的方法来做到这一点(主要是为了代码清晰使用 method
因为 sub
感觉......误导)?
关于误导:FETCH
和 STORE
值预期 Callables
,可能是 method
或 sub
。
回到问题,没有直接的方法,但是有更好的间接方法,可能更清楚。您可以先设置 multi sub
,然后将 proto
作为参数传递:
proto sub store(|) {*}
multi sub store(\self, Int) { say "Int" }
multi sub store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str
如果你想让代码更短,但可能更难理解,你可以去掉 proto
(因为它会自动为你生成)和 sub
multi
(因为你可以):
multi store(\self, Int) { say "Int" }
multi store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str