В Perl зачем мне @b = @ {dclone (\ @ a)}? Почему я не могу просто @b = dclone (\ @ a)? - PullRequest
4 голосов
/ 06 января 2010

У меня есть множество различных вещей, включая скаляры и массивы. Я хочу сделать копию и попробовал следующее:

@b = dclone(\@a)

но потом, когда я пытаюсь прочитать одно из скалярных значений из b, я ничего не получаю обратно.

Кажется, все работает, когда я копирую его таким образом:

@b = @{dclone(\@a)}

В чем причина?

Ответы [ 3 ]

14 голосов
/ 06 января 2010

dclone принимает и возвращает ссылки.

#! /usr/bin/perl

use Storable qw/ dclone /;

my @array = ( [1 .. 3], qw/ apple orange banana / );
my $copy = dclone \@array;

print ref($copy), "\n";

Вывод программы выше ARRAY, поэтому для получения глубоко клонированного массива используйте

my @copy = @{ dclone \@array };

Чтобы показать, что происходит без разыменования, вывод

my @copy = dclone \@array;

for (0 .. 4) {
  print "$_: ",
        (defined $copy[$_] ? $copy[$_] : "<undef>"),
        "\n";
}

есть

0: ARRAY(0x1d396c8)
1: <undef>
2: <undef>
3: <undef>
4: <undef>

Таким образом, присвоение результата dclone массиву приведет к созданию одноэлементного массива, а попытка получить любое значение, кроме нуля, приведет к неопределенному значению.

2 голосов
/ 07 января 2010

Как говорит пара человек, dclone принимает и возвращает ссылки. Это достаточно хорошо, но я думаю, что есть также вопрос почему?

Как видно из документации для Storable, dclone( ... ) эквивалентно составу thaw и freeze как thaw( freeze( ... )). thaw может оттаивать любой тип кодированной структуры. Ссылка может ссылаться на что угодно в Perl. Тот массив хэшей массивов, который вы хотели, хеш хэшей массивов, ... Он полагается на вас , чтобы знать, о чем вы просили - и если нет, то по крайней мере для вас немного озадачить.

Однако, если вам действительно не нравится синтаксис, и вы будете использовать идиому ARRAY -> ARRAY для того, чтобы он выглядел лучше, вы можете написать функцию-обертку примерно так:

sub dclone_array (\@) { 
    use Storable 'dclone';
    my $in  = shift;
    my $out = dclone( $in );
    return @$out;
}

И используйте это как:

my @copy = dclone_array( @orig );
2 голосов
/ 06 января 2010

Вам необходимо разыменовать возвращаемое значение dclone, которое является указателем (ссылка).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...