在Perl中仅通过引用传递一些子例程参数
我正在写一个包含许多参数的子程序。大多数参数都是标准的按值传递排序,在子例程中对它们所做的更改在子例程之外并不重要。但其中一个是一个对象(祝福引用),我想对其进行更改,如果传入的话,可以在子例程之外进行更改。如果没有传入,我想实例化它,并以传入的方式处理它(但最终返回它) 例如:在Perl中仅通过引用传递一些子例程参数,perl,pass-by-reference,Perl,Pass By Reference,我正在写一个包含许多参数的子程序。大多数参数都是标准的按值传递排序,在子例程中对它们所做的更改在子例程之外并不重要。但其中一个是一个对象(祝福引用),我想对其进行更改,如果传入的话,可以在子例程之外进行更改。如果没有传入,我想实例化它,并以传入的方式处理它(但最终返回它) 例如: 我希望使用尽可能干净的语法来实现这一点,并且我可以使用PerlV5.22及更高版本中提供的任何功能。(我已经尝试过使用重构来解决这个问题,但它不是很干净。) 我缺少什么?首先,子程序参数总是通过引用传递 $ pe
我希望使用尽可能干净的语法来实现这一点,并且我可以使用PerlV5.22及更高版本中提供的任何功能。(我已经尝试过使用
重构
来解决这个问题,但它不是很干净。)
我缺少什么?首先,子程序参数总是通过引用传递
$ 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);
首先,子例程参数总是通过引用传递
$ 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);
“我错过了什么?”,没什么。您的代码按原样工作。Re“大多数参数都是标准的按值传递排序”,Perl总是按引用传递。例如,
perl-e'subf{$\u0]=“def”}my$x=“abc”;f(x美元);核心::比如说$x;'代码>输出def
。呸,你说得对,这看起来确实有效。我之前尝试过的一些事情给了我错误;我想他们没有关系。另外,我称之为“按值传递”的是标准的my($foo)=@
,在我的示例(而不是您的示例)中,它直接出现在子例程的开头。在收到参数后复制这些参数不会改变它们通过引用传递的事实。你复制了一个论点的事实并不能阻止你改变论点。如果你问“我遗漏了什么?”,没什么。您的代码按原样工作。Re“大多数参数都是标准的按值传递排序”,Perl总是按引用传递。例如,perl-e'subf{$\u0]=“def”}my$x=“abc”;f(x美元);核心::比如说$x;'代码>输出def
。呸,你说得对,这看起来确实有效。我之前尝试过的一些事情给了我错误;我想他们没有关系。另外,我称之为“按值传递”的是标准的my($foo)=@
,在我的示例(而不是您的示例)中,它直接出现在子例程的开头。在收到参数后复制这些参数不会改变它们通过引用传递的事实。您复制了一个参数的事实并不能阻止您更改参数。您的清理方法返回$foo
,而不管$arg1
的值是多少,这与我的示例不同。另外,我遗漏了如果$foo
未定义,我还有其他代码要运行,因此/=
在这里对我没有多大帮助。Re“您的清理方法返回$foo,而不管$arg1的值如何,这与我的示例不同。”,那又怎样?我从来没有说过它是一样的;我说它更干净。Re“我忘了如果$foo未定义,我还有其他代码要运行”,您可以通过检查@
的大小来检查提供的参数数量。也就是说,在你提出这个问题之前,你的电话会议已经过于复杂了。区分不存在的参数和未定义的参数太过分了。添加了更简单的调用约定来回答。无论$arg1
的值是多少,清理后的方法都会返回$foo
,这与我的示例不同。另外,我遗漏了如果$foo
未定义,我还有其他代码要运行,因此/=
在这里对我没有多大帮助。Re“您的清理方法返回$foo,而不管$arg1的值如何,这与我的示例不同。”,那又怎样?我从来没有说过它是一样的;我说它更干净。Re“我忘了如果$foo未定义,我还有其他代码要运行”,您可以通过检查@
的大小来检查提供的参数数量。也就是说,在你提出这个问题之前,你的电话会议已经过于复杂了。区分缺少的参数和未定义的参数太过分了。添加了更简单的调用约定来回答。