URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9918
[ Назад ]

Исходное сообщение
"почему если %tmp=%hash, то изменяются оба??"

Отправлено greenwar , 15-Окт-14 00:19 
доброй ночи
присваиваю %tmp=%hash и работаю ТОЛЬКО с %tmp, но при этом данные в %hash также меняются.
не меняются они, только если прогнать while по всему %hash и поскалярно перекинуть данные в %tmp
т.е. $tmp{$key}=$hash{$key}
это баг или фича?

Содержание

Сообщения в этом обсуждении
"почему если %tmp=%hash, то изменяются оба??"
Отправлено XAnder , 15-Окт-14 08:51 
> присваиваю %tmp=%hash и работаю ТОЛЬКО с %tmp, но при этом данные в
> %hash также меняются.

Вообще-то не должно быть такого. Вот минимальный пример:

$ perl -MData::Dumper -E '%hash=(key=>"foo"); %tmp=%hash; $tmp{key}="bar"; print Dumper \%hash, \%tmp'
$VAR1 = {
          'key' => 'foo'
        };
$VAR2 = {
          'key' => 'bar'
        };

Приведите минимальный пример, где наблюдается поведение, которое вы описали. Не используются ли там ссылки?


"почему если %tmp=%hash, то изменяются оба??"
Отправлено greenwar , 15-Окт-14 12:30 
>[оверквотинг удален]
> $VAR1 = {
>           'key' =>
> 'foo'
>         };
> $VAR2 = {
>           'key' =>
> 'bar'
>         };

> Приведите минимальный пример, где наблюдается поведение, которое вы описали. Не используются
> ли там ссылки?

строго говоря это хеш хешей, а с простым хешем всё ок:

my%hash=(
'cat'=>{
1=>['20','21'],
2=>['30','31']
}
);

my%tmp=%hash;

$tmp{cat}{1}[0]=25;

print"$hash{cat}{1}[0]\n";


"почему если %tmp=%hash, то изменяются оба??"
Отправлено XAnder , 15-Окт-14 12:44 
> строго говоря это хеш хешей, а с простым хешем всё ок:

Ага, ссылки.

> my%hash=(
> 'cat'=>{
> 1=>['20','21'],
> 2=>['30','31']
> }
> );

Тут один именованный хеш (%hash), один безымянный хеш и два безымянных массива. Всё это хозяйство связанно друг с другом ссылками.

%hash содержит один элемент - скаляр $hash{cat}, который является ссылкой на безымянный хеш.

> my%tmp=%hash;

Новый хеш %tmp содержит то же, что и старый: одну ссылку на тот же самый безымянный хеш. Естественно его копия не была создана.

Теперь $hash{cat} и $tmp{cat} - один и тот же хеш. Обращаться к нему можно и так, и так.

> $tmp{cat}{1}[0]=25;

Тут мы поменяли что-то в недрах всё того же безымянного хеша.

> print"$hash{cat}{1}[0]\n";

И получили закономерный результат.


"почему если %tmp=%hash, то изменяются оба??"
Отправлено greenwar , 15-Окт-14 13:02 
>[оверквотинг удален]
> хеш.
>> my%tmp=%hash;
> Новый хеш %tmp содержит то же, что и старый: одну ссылку на
> тот же самый безымянный хеш. Естественно его копия не была создана.
> Теперь $hash{cat} и $tmp{cat} - один и тот же хеш. Обращаться к
> нему можно и так, и так.
>> $tmp{cat}{1}[0]=25;
> Тут мы поменяли что-то в недрах всё того же безымянного хеша.
>> print"$hash{cat}{1}[0]\n";
> И получили закономерный результат.

ну а как правильно?


"почему если %tmp=%hash, то изменяются оба??"
Отправлено XAnder , 15-Окт-14 13:32 
> ну а как правильно?

Трудно сказать, от задачи зависит. В общем случае для копирования сложной структуры можно сделать рекурсивную функцию.


"почему если %tmp=%hash, то изменяются оба??"
Отправлено greenwar , 15-Окт-14 13:38 
>> ну а как правильно?
> Трудно сказать, от задачи зависит. В общем случае для копирования сложной структуры
> можно сделать рекурсивную функцию.

ну у меня пока решение такое:
while(my$key1 = each %hash)
{
    while(my$key2 = each %{$hash{$key1}})
    {
        $tmp{$key1}{$key2}[0]=$hash{$key1}{$key2}[0];
        $tmp{$key1}{$key2}[1]=$hash{$key1}{$key2}[1]
    }
}

но если массив будет помассивней, херня получится


"почему если %tmp=%hash, то изменяются оба??"
Отправлено Pahanivo , 15-Окт-14 14:49 
>[оверквотинг удален]
> ну у меня пока решение такое:
> while(my$key1 = each %hash)
> {
>     while(my$key2 = each %{$hash{$key1}})
>     {
>         $tmp{$key1}{$key2}[0]=$hash{$key1}{$key2}[0];
>         $tmp{$key1}{$key2}[1]=$hash{$key1}{$key2}[1]
>     }
> }
> но если массив будет помассивней, херня получится

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


"почему если %tmp=%hash, то изменяются оба??"
Отправлено greenwar , 15-Окт-14 15:30 
>[оверквотинг удален]
>>     {
>>         $tmp{$key1}{$key2}[0]=$hash{$key1}{$key2}[0];
>>         $tmp{$key1}{$key2}[1]=$hash{$key1}{$key2}[1]
>>     }
>> }
>> но если массив будет помассивней, херня получится
> ну дак вы учитесь таки пользоваться перлом.
> вам же правильно говорят - делайте функцию копирования для структуры,
> а то ни про ссылки не знаете, ни про циклы по массиву
> ...

о блять, знаток вылез
а зачем же там функция отдельная, когда можно прям там же:
my@tmp=@{$hash{$key1}{$key2}};
for(0..$#tmp){$tmp{$key1}{$key2}[$_]=$hash{$key1}{$key2}[$_]}

учитесь таки пользоваться перлом (c)

и читать. вопрос был: как упростить до %tmp=%hash


"почему если %tmp=%hash, то изменяются оба??"
Отправлено XAnder , 15-Окт-14 16:12 
> а зачем же там функция отдельная, когда можно прям там же:
> my@tmp=@{$hash{$key1}{$key2}};
> for(0..$#tmp){$tmp{$key1}{$key2}[$_]=$hash{$key1}{$key2}[$_]}

Как я и писал, зависит от задачи. Здесь такой способ годится, в другом случае может и нет. Мы ваших задач не знаем, а общий случай слишком заковыристый, чтобы объяснить в двух строчках на форуме и написать в двух строчках на Пёрле. Как, например, будете обрабатывать циклические ссылки? В общем случае они, конечно же, есть. А всякие blessed объекты, требующие инициализации? Их нельзя просто так копировать.

PS. Моё личное вам «фи» за ответ хамством на хамство по нарастающей. А Pahanivo тут штатный, пора бы привыкнуть. Я его когда-то чайникодавом назвал, и он по-прежнему оправдывает это звание :-)


"почему если %tmp=%hash, то изменяются оба??"
Отправлено Pahanivo , 15-Окт-14 22:26 
шо вы таки меня палите ))



"почему если %tmp=%hash, то изменяются оба??"
Отправлено ACCA , 29-Окт-14 21:33 

use Storable qw(dclone);
[...]
%tmp = %{ dclone( \%hash ) };