ProgrammatieBackend ontwikkelaar

Hoe werken lexicale en pakkett variabelen in Perl: wat zijn de verschillen tussen my, our en state, wanneer deze correct te gebruiken, en welke fouten komen er in de praktijk voor?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Perl zijn er drie hoofdtypen variabelenverklaring: my, our en state.

  • my creëert een lexicale variabele met zichtbaarheid binnen het blok code (lexicale scopering).
  • our creëert een pakkett variabele die globaal toegankelijk is binnen het pakket, maar alleen zichtbaar is in het lexicale blok. Dit is nuttig voor het organiseren van naamruimtes tussen modules.
  • state is toegevoegd in Perl 5.10 en creëert een lexicale variabele die zijn waarde tussen oproepen van de subroutine onthoudt (in wezen een statische variabele).
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Geeft 1, dan 2, dan 3 }

Waar correct te gebruiken:

  • my — bijna altijd de voorkeur voor variabelen, tenzij er een reden is voor globale toegang.
  • our — voor het exporteren van variabelen tussen modules, wanneer gedeeld gebruik vereist is.
  • state — als de variabele een waarde moet "onthouden" tussen aanroepen van de functie (bijvoorbeeld, een aanroep teller).

Misleidende vraag

Kan een variabele die met our is gedeclareerd, worden vastgelegd (captured) in een closure zoals my?

Meestal antwoorden mensen "ja, dat is handig", maar dat is niet waar. Een our variabele is globaal voor het pakket, en een closure bindt haar waarde op het moment van creatie niet, maar benadert deze via de globale naam. Daarom kan haar "waarde" van buiten de closure veranderen, wat alle closures beïnvloedt!

our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Geeft 42 terug, niet 10

Voorbeelden van echte fouten door gebrek aan kennis van de details


Verhaal

In een groot script voor log parsing werden variabelen gedeclareerd met our voor "gemakkelijke toegang" vanuit verschillende functies van het module. Als gevolg daarvan leidde het wijzigen van deze variabelen in één functie tot onverwacht gedrag in een andere, wat de parallelle verwerking van logs verstoorde.


Verhaal

Het gebruik van my voor variabelen waarvan de waarde moest worden onthouden tussen aanroepen van de functie (bijvoorbeeld, een teller binnen een recursieve doorloop) leidde tot het resetten van de waarde bij elke oproep, wat leidde tot onjuiste doorlooplogica. Vervangen door state loste het probleem op.


Verhaal

Onjuist gebruik van our in een geïmporteerd module (export van variabelen niet via Exporter) leidde tot naamconflicten bij het opnemen van twee verschillende modules die dezelfde variabelenaam gebruikten. Hierdoor "sprongen" gegevens van de ene context naar de andere.