我正在写一个带有许多参数的子程序。这些参数中的大多数是标准的按值传递排序,其中在子例程内对它们进行的更改在其外部并不重要。但其中一个是一个对象(祝福参考),我想对子程序之外的内容进行更改,如果它已经传入。如果它没有传入,我我希望实例化它并以与传入它相同的方式处理它(但最后将其返回)。
例如:
my $foo = Private::Foo->new();
# $foo->{'something'} eq 'old value'
Private::Foo->do_things('abc', 'xyz', $foo);
# $foo->{'something'} eq 'new value'
my $foo2 = Private::Foo->do_things('def');
# $foo2->{'something'} eq 'old value'
package Private::Foo;
# ...
sub do_things {
my ($self, $arg1, $arg2, $foo) = @_;
unless (defined $foo) {
$foo = Private::Foo->new();
}
if ($arg1 eq 'abc') {
$foo->{'something'} = 'new value';
return;
}
return $foo;
}
我希望尽可能使用尽可能简洁的语法,并且我可以使用Perl v5.22及更高版本中提供的任何功能。 (我已经尝试使用refaliasing
弄清楚如何执行此操作,但它并不是很干净。)
我错过了什么?
答案 0 :(得分:0)
首先,子程序参数始终通过引用传递。
$ perl -e'sub f { $_[0] = "def"; } my $x = "abc"; f($x); CORE::say $x;'
def
更重要的是,您的代码完全按照您的要求执行。
$ perl -e'
{
package Private::Foo;
sub new { my $class = shift; bless({ something => "old_value" }, $class) }
sub do_things {
my ($self, $arg1, $arg2, $foo) = @_;
unless (defined $foo) {
$foo = Private::Foo->new();
}
if ($arg1 eq "abc") {
$foo->{something} = "new value";
return;
}
return $foo;
}
}
use feature qw( say );
my $foo = Private::Foo->new();
Private::Foo->do_things("abc", "xyz", $foo);
say $foo->{something};
my $foo2 = Private::Foo->do_things("def");
say $foo2->{something};
'
new value
old_value
那就是说,你可以清理一下你的方法:
sub do_things {
my ($class, $arg1, $arg2, $foo) = @_;
$foo //= $class->new();
if ($arg1 eq 'abc') {
$foo->{something} = 'new value';
}
return $foo;
}
如果你清理了你的召唤惯例会更好。
Private::Foo->do_something($arg1, $arg2, $foo);
my $foo2 = Private::Foo->do_something($arg1, $arg2);
远不如
$foo->do_something($arg1, $arg2);
( my $foo2 = Private::Foo->new )->do_something($arg1, $arg2);