4

好的,所以很容易创建对数组的引用......

my @a;
my $b=\@a;
#can now reference the same list of scalars from either @$b or @a

但是我怎么能反过来呢?例如:

my $a=[1..4];
my @b;
#some magic happens here and now @b is an alias for @$a
@b=(6..10);
print "@$a\n";  #should print "6 7 8 9 10"

我认为这会通过 typeglobs 发生,但那些只是让我望而却步。想法?

对哈希和数组做同样的事情也会很好。

编辑:这似乎可行,但它有点笨拙,因为它只是将匿名数组元素复制到“别名”,然后将自身重新指向数组:

my @b=@$a;
$a=\@b;

有更好的想法吗?

4

4 回答 4

8

三种方式:

  1. 重新混淆。

    5.22 添加了一个实验性功能,可以完全满足您的需求。

    use experimental qw( refaliasing );
    \my @B = $A;
    

    5.26 添加了第二个实验功能,允许以下操作:

    use experimental qw( refaliasing declared_refs );
    my \@B = $A;
    

    请注意,作为实验性功能,这些功能可能随时更改和删除。

  2. 全局混叠

    Perl 将其符号表条目数据结构称为“type glob”,或简称为“glob”。可以将此数据结构中的条目设置为引用以命名该引用。

    local our @B;
    *B = $A;      # Sets the array slot of "B", @B.
    

    请注意,我们必须使用包变量,因此该变量是全局可见的。

  3. 数据::别名

    alias my @B = @$A;
    
于 2012-12-28T14:59:42.013 回答
6

perl 程序中的所有变量都存储在命名空间中。有两种类型的命名空间:

  1. 符号表。它是一个全局哈希,存储全局变量的记录。
  2. 词法范围。它是存储的匿名临时内存,不是特定的符号表,而是附加到程序的块中。它们存储我们只能在该程序块中看到的变量。

Typeglob 用于定义符号表的记录(变量、数组等),但不用于定义词法范围。因此,当您使用这部分代码时:

my @b;
*b = $a;

你会得到的:

Name "main::b" used only once:

这表明我们没有在符号表中定义记录 main::b,但我们可以使用修饰符“ our ”来做到这一点。因此,当你这样写时:

our @b;
*b = $a;

我们可以获得对我们有用的结果,因为 *b 存储在符号表中,我们可以使用运算符 * typeglob。

于 2012-12-28T15:32:41.483 回答
3

我想我明白了...

my $a=[1..4];
our @b;
*b=$a;
print "@b\n";
@b=(6..10);
print "@$a\n";

印刷:

1 2 3 4
6 7 8 9 10

“我们的”对我来说仍然有点神秘......我想我有一些阅读要做......

于 2012-12-28T14:43:33.773 回答
0

$a 和 @a 不是一回事。$a,当您第一次分配它时,它是对匿名数组的引用。它与@a 没有任何关系,@a 是一个数组(不是引用)。

$b = \@a # $b 持有对@a 的引用,但不持有对$a 的引用。

$a、@a、%a 都是不同的变量。所以,如果你有

我的@a = (1,2,3,4);

然后你声明

我的$a;

$a 不包含对@a 的引用;

变量按其类型保存在符号表中;标量、散列、数组等。这样你就可以拥有$a、@a、%a、&a ...并且它们不会相互冲突。

重点是

#some magic happens here and now @b is an alias for @$a

不会发生。它仍然指向内存中存储 @a 的区域,这与存储 $a 的位置不同。

于 2012-12-28T13:48:53.947 回答