【问题标题】:Passing arrays to functions in Perl将数组传递给 Perl 中的函数
【发布时间】:2011-11-06 10:53:46
【问题描述】:

我想我误解了 Perl 中将参数传递给函数的某些方面。 func(\@array)func(@array)有什么区别?

AFAIK,在这两个函数中,参数都是通过引用传递的,在这两个函数中,我们可以在主程序中更改 @array 的元素。那么有什么区别呢?我们什么时候应该使用哪个?

@array = (1,2,3);
func(@array);
func(\@array);

sub func {
    ...
}

另外,如何在 Perl 中模拟传递值?使用@_ 是唯一的方法吗?

【问题讨论】:

  • 这样的问题如何获得如此多的支持?

标签: perl function parameter-passing


【解决方案1】:

不可能将数组传递给 subs。 Subs 采用标量列表作为参数。 (这也是他们唯一可以返回的东西。)

您可以传递对数组的引用:

func(\@array)

你可以传递数组的元素:

func(@array)

我们什么时候应该使用哪个?

如果您想传递的不仅仅是数组的元素(例如传递 $x$y@a),除非您传递引用,否则可能会变得很棘手。

如果您要处理列表(例如 sum mysub grep { ... } ...),您可能不想传递引用。

如果你想修改数组(而不是仅仅修改数组的现有元素),你需要传递一个引用。

为长数组传递引用可能更有效,因为创建一个引用并将其放入堆栈比为大数组的每个元素创建别名要快。不过,这很少会成为问题。

通常由上述前两项中的一项决定。除此之外,这主要是个人喜好问题。


另外,如何在 Perl 中模拟传递值?
sub foo {
   my ($x) = @_;   # Changing $x doesn't change the argument.
   ...
}

sub foo {
   my @a = @_;   # Changing @a or its contents
   ...           #    doesn't change the arguments.
}

【讨论】:

  • (And that's the only thing they can return too.) 不,他们可以返回数组。要查看它,请查看标量上下文中 sub { return (qw/a b c/);}sub { @array = (qw/a b c/); return @array } 之间的区别。这个第一个返回c,第二个返回3,返回数组的元素个数!!!
  • @Joel,不,他们不能返回数组。标量上下文中的sub { return (qw/a b c/);} 返回一个标量(“c”),而标量中的sub { @array = (qw/a b c/); return @array } 返回一个标量(3)。在评估 return 之前,qw@array 返回标量。
  • @TLP,您的测试中一定有错误。试试perl -E"say scalar sub { return (qw/a b c/);}->()"
  • @Joel,您可以看到使用此 XS 代码返回数组时会发生什么:void f() { dXSARGS; EXTEND(SP, 1); ST(0) = newAV(); XSRETURN(1); }。如果你做$x = f();,你会得到Bizarre copy of ARRAY in scalar assignment
【解决方案2】:

AFAIK,在这两个函数中,参数都是通过引用传递的,在这两个函数中,我们可以在主程序中更改 @array 的元素。

“改变元素”,是的。但是,在func(@array) 的情况下,子无法对数组进行其他更改(截断、推送、弹出、切片、传递对其他内容的引用,甚至取消定义)。

我会避免使用术语“通过引用传递”,因为该机制与 Perl 的引用完全不同。它不那么重载:) 说在 sub 中,@_ 的元素开始别名为传递给 sub 的元素。

【讨论】:

    【解决方案3】:

    func(\@array) 传递一个引用。 func(@array) 传递一个列表(@array 中的元素)。正如基思所指出的,这些元素是通过引用传递的。但是,您可以在 sub 内部进行复制以便按值传递。

    你追求的是这个:

    sub func {
        my @array = @_;
    }
    

    这会将func 的参数副本传递给@array,这是子例程范围内的局部变量。

    文档here

    【讨论】:

    • 其实func(@array)通过引用传递@array的元素。例如:sub func { map { $_ ++ } @_; } } my @arr = ( 10, 20, 30); func(@arr); 会将@arr 设置为(11, 21, 31) -- 并且func(10, 20, 30) 将失败并显示“尝试修改只读值”。 my @arr = @_; 成语的一个目的是将@_ 的值复制到本地数组中,以达到传值的效果。
    • 正如perldoc perlsub 所说:“传入的任何参数都显示在数组@_ 中。因此,如果您调用带有两个参数的函数,这些参数将存储在$_[0] 和@987654339 @. 数组@_ 是一个本地数组,但它的元素是实际标量参数的别名。”
    • re "by reference",看我的回答
    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 2018-10-21
    相关资源
    最近更新 更多