没有引用的Perl参数修改

时间:2016-06-09 07:09:53

标签: perl

我只是想要在不使用引用的情况下修改Perl子例程中的参数的概念。我在数组的情况下试过这个:

sub test {
  print "Trying to change ... \n";
  $_[0] = "Third";
  $_[1] = 100;
}

@a = ("First", 1, "Second", 2);

print "Before change : @a \n";
test(@a);
print "After change : @a \n";

输出:

Before change : First 1 Second 2
Trying to change ...
After change : Third 100 Second 2

换句话说,通过更改@_的值来更改数组的元素。

但是在哈希的情况下做同样的事情并没有给出预期的行为:

sub test {
  print "Trying to change ... \n";
  $_[0] = "Third";
  $_[1] = 100;
}

%h = ("First" => 1, "Second" => 2);

test(%h);

foreach ( keys %h ) {
  print "$_\n";
}

输出:

Trying to change ...
Second
First

为什么这两种情况会有所不同?

3 个答案:

答案 0 :(得分:3)

你被误导了

Perl哈希键不是普通的Perl标量值 - 它们存储为速度的简单C字符串,但哈希值 Perl标量

在类似test(%h)的调用中,Perl从每个哈希键字符串中创建一个临时Perl标量,并将这些标量与真实哈希值标量一起传递

这意味着任何修改键字符串的尝试都只会更改临时标量,并且不会反映在哈希中。但是您的代码更改值

这是一个在子例程调用之前和之后转储整个哈希的版本。您可以看到字符串Third已丢失,但100已分配给(随机)哈希值

use strict;
use warnings 'all';

use Data::Dump 'pp';

sub test {
  $_[0] = "Third";
  $_[1] = 100;
}

my %h = ("First" => 1, "Second" => 2);

printf "Before: %s\n", pp \%h;
test(%h);
printf "After:  %s\n", pp \%h;

输出

Before: { First => 1, Second => 2 }
After:  { First => 1, Second => 100 }

答案 1 :(得分:2)

数组声明和哈希声明不是一回事。当你在做的时候  哈希函数中的 $ _ [0] ="第三&#34 ;; ,那么您不会更改哈希内容。它仅用于数组。

删除第一个键。您需要使用删除操作符将其删除,然后添加第三个键。所以,没有参考就不可能。

答案 2 :(得分:2)

Perl将一直通过引用传递。

因此,在数组示例中,每个元素都作为引用传递(因为对子的输入只是'缩放器列表',即数组)。因此,当您更新sub中的元素时,实际上会更改引用原始数组中的值的值。

在散列的示例中,当Perl看到传递给子的散列时,它知道它不能发送散列,因此将其转换为散列数据的“缩放器列表”表示 - 这不是关键对原始数据的引用。此表示形式通过引用传递给您更新。因此,您不会像使用简单数组那样更新原始数据。