ProgrammatiePerl-gegevensverwerkingsspecialist

Hoe werken interne gegevensstructuren (arrays van arrays, hashes van hashes en gemengde typen) in Perl, en welke valkuilen kunnen ontstaan bij hun creatie en gebruik?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Arrays van arrays, hashes van hashes en andere complexe gegevensstructuren worden in Perl gebouwd met behulp van verwijzingen. Deze aanpak maakt het gemakkelijk om hiërarchische/vertakte structuren te creëren, maar vereist voorzichtigheid bij het aanspreken, kopiëren en wijzigen, omdat standaard de verwijzing wordt opgeslagen en niet de inhoud.

Geschiedenis van de vraag

Oorspronkelijk ondersteunde Perl alleen platte arrays en hashes, zonder nesteling. Later kwam er ondersteuning voor verwijzingen, waardoor elke combinatie mogelijk werd: arrays van arrays, hashes van hashes, structuren zoals "boom", "graf" etc.

Probleem

Werken met complexe structuren vereist dat men zich herinnert dat de bewerkingen voor aanspreken, schrijven en kopiëren met verwijzingen werken. Fouten ontstaan vaak door verwarring tussen het element en de verwijzing naar het element. Dit leidt tot talrijke bugs, bijvoorbeeld, het wijzigen van gegevens op één plek heeft invloed op de gehele structuur, als de verwijzing door meerdere delen van het programma tegelijkertijd wordt gebruikt.

Oplossing

Voor het maken van een array van arrays:

my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2

Voor een hash van hashes:

my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;

Gemengde structuren:

my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );

Belangrijke kenmerken:

  • Het werken met geneste structuren gaat altijd via verwijzingen, zelfs als dit aanvankelijk niet duidelijk is.
  • Voor diepe kopieën is een eenvoudige toewijzing niet voldoende.
  • Fouten zijn vaak gerelateerd aan het niet onmiddellijk zichtbaar zijn van het type gegeven/structuur.

Misleidende vragen.

Wat gebeurt er als je probeert een array aan een andere toe te wijzen om de structuur te kopiëren?

Zo'n toewijzing kopieert geen geneste structuren, maar alleen de verwijzingen ernaar (dat wil zeggen, er vindt een "oppervlakkige kopie" plaats).

my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # Geeft 99 weer, omdat @b verwijzingen naar dezelfde arrays bevat als @a

Wat is het verschil tussen toegang tot een element als $array[$i] versus $array->[$i]?

De eerste variant werkt als we een array hebben, de tweede werkt als we een scalaar hebben die naar een array verwijst. Voor geneste structuren is de meest voorkomende syntaxis de pijl ($foo->[0]).

Waarom kun je gewoon geen kopie van de structuur maken met dclone in de standaard Perl?

Omdat dclone niet is opgenomen in de basislevering van Perl. Voor het maken van diepe kopieën van complexe structuren gebruikt men de Storable-module en de functie dclone:

use Storable 'dclone'; my $deep_copy = dclone(\%complex);

Typische fouten en anti-patterns

  • Toewijzing van een complexe structuur "zoals het is" zonder gebruik te maken van diepe kopieëen.
  • Foutieve toegang tot een element zonder rekening te houden met het feit dat we een verwijzing hebben (of geen verwijzing).
  • Poging om een complexe structuur te serialiseren zonder rekening te houden met de nesteling en verwijzingen.

Voorbeeld uit het leven

Negatieve case

In een project worden arrays van arrays gekopieerd via gewone toewijzing (@copy = @org), en na een reeks wijzigingen merken ze plotseling dat de gegevens van de "origineel" zijn gewijzigd samen met de kopie.

Voordelen:

  • Snel
  • Eenvoudige syntaxis

Nadelen:

  • Hoge kans op verborgen bugs
  • Impliciete wijziging op verschillende delen van het programma.

Positieve case

Men gebruikt de Storable-module en de functie dclone voor het kopiëren van arrays en hashes, waarbij dit expliciet wordt gedocumenteerd in de code en duidelijk wordt onderscheiden waar de verwijzing is en waar deze niet is.

Voordelen:

  • Correcte duplicatie van gegevens
  • Duidelijke structuur van de code
  • Minder onaangename verrassingen

Nadelen:

  • Men moet zich bewust zijn van extra afhankelijkheden
  • Het is gemakkelijk om de noodzaak van diepe kopieën in nieuwe plaatsen te vergeten.