Thread Umfangreiche Hash Referenz mit Regex und Code kopieren (20 answers)
Opened by bianca at 2016-02-26 09:38

clms
 2016-03-05 16:42
#184051 #184051
User since
2010-08-29
373 Artikel
BenutzerIn
[default_avatar]
2016-02-27T00:18:14 pq
pack mal ein
$neu->{code} = sub { say "neu" };
nach das clone und guck, was sich ändert =)

interessanterweise wird das im unterschied zu arrays erst wirklich kopiert, wenns verändert wird. copy-on-write

Ich kann da kein Copy-on-write erkennen.

clone kopiert alle ineinandergeschachtelten Hashes, Arrays und Scalars incl. der Referenzen auf ausführbare Funktionen, aber nicht die ausführbaren Funktionen selbst. Deshalb haben $alt->{code} und $neu->{code} zunächst den gleiche Wert - sie verweisen auf die gleiche Funktion.
Mit $neu->{code} = sub { say "neu" }; wird eine komplett neue Funktion angelegt und eine Referenz darauf in $neu->{code} gespeichert. Die alte Funktion wird dabei nicht kopiert. Genauso wenig wird der Hash $neu oder der Key code kopiert (das wurde schon mit clone() gemacht).

Aber wie schon geschrieben, ob die Original-Funktion oder eine Kopie der selben verwendet wird, macht nur dann einen Unterschied wenn state-Variablen o.ä. verwendet werden.

Hier ein Beispiel, wo man etwas besser sehen kann, was passiert:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use v5.10;
use Clone 'clone';

my $alt = {
  array => [1,2],
  code => sub{state $i; return ++$i }
};

my $neu = clone $alt;

if ($neu->{array} eq $alt->{array}) {
  say "Das Array wurde nicht kopiert";
} else {
  say "Das Array wurde kopiert";
}

if ($neu->{code} eq $alt->{code}) {
  say "Die Funktion wurde nicht kopiert";
} else {
  say "Die Funktion wurde kopiert";
}
say "alt1: ".($alt->{code}->());   # alt1: 1
say "alt2: ".($alt->{code}->());   # alt2: 2
say "neu1: ".($neu->{code}->());   # neu1: 3  - state von "alt" wird weiter inkrementiert, weil es die gleiche Funktion ist
say "neu2: ".($neu->{code}->());   # neu1: 4  

$neu->{code} = sub{state $i; return ++$i };

say "neu1-neu: ".($neu->{code}->()); # neu1-neu: 1   - jetzt ist es eine neue state-Variable 
say "neu2-neu: ".($neu->{code}->()); # neu2-neu: 2 
if ($neu->{code} eq $alt->{code}) {
  say "Die Funktion ist noch die gleiche";
} else {
  say "Die Funktion ist eine andere";
}

View full thread Umfangreiche Hash Referenz mit Regex und Code kopieren