Achtergrond:
In Perl zijn subprogramma's vanaf het begin zeer flexibel geïmplementeerd: elke aanroep van een subprogramma kan een onbeperkt aantal parameters accepteren, die in de array @_ worden geplaatst. Deze aanpak is geschikt voor taken van verschillende complexiteit en ondersteunt de dynamiek van Perl.
Probleem:
Veel ontwikkelaars, vooral beginners, stuiten op verwarring bij het werken met @_ — onjuiste destructurering van parameters, onopzettelijke wijziging van invoergegevens (omdat variabelen naar waarde worden doorgegeven en complexe structuren naar referentie), en discrepantie tussen het aantal en de typen argumenten. Problemen doen zich voor bij het teruggeven van verschillende gegevenstypes en bij het proberen om prototypering van functies te implementeren.
Oplossing:
Om argumenten te verkrijgen, moet de subprogramma expliciet de destructurering vanuit de array @_ uitvoeren. Waarde teruggave gebeurt via het return-statement, waarbij het gedrag afhangt van de context (schaalar of lijst). Om bijeffecten te vermijden, worden parameters vaak als kopie of als referentie genomen, als wijziging binnen het subprogramma vereist is. Voor complexe structuren wordt referentiedoorvoer gebruikt.
Voorbeeldcode:
sub add { my ($a, $b) = @_; return $a + $b; } sub change_array { my ($arr_ref) = @_; push @$arr_ref, 100; } my @nums = (1, 2, 3); my $sum = add(5, 10); change_array(\@nums); print join(", ", @nums); # 1, 2, 3, 100
Belangrijkste kenmerken:
@_Verandert de functie de parameters die aan haar zijn doorgegeven als je met eenvoudige scalars werkt?
Nee, scalars worden gekopieerd tijdens de overdracht, hun wijzigingen raken het origineel niet. Maar als het argument een referentie is, kunnen de oorspronkelijke gegevens veranderen.
Kun je standaardwaarden voor argumenten in subprogramma's instellen, zoals in andere talen?
Direct niet. In Perl moet je zelf de verwerking van standaardwaarden in het lichaam van de functie implementeren, door gebruik te maken van een gedefinieerde controle of het aantal argumenten.
Voorbeeldcode:
sub foo { my ($arg1, $arg2) = @_; $arg2 //= 10; print "$arg1 $arg2 "; } foo(5); # 5 10
Wat gebeurt er als je rechtstreeks toegang krijgt tot @_ zonder kopiëren - bijvoorbeeld, $a = $_[0]?
Zo'n toewijzing creëert een alias: wijziging van $a verandert $[0] en vice versa. Het wordt aanbevolen om kopieën te maken via my ($a) = @; om onverwachte wijzigingen te voorkomen.
** Negatieve case
In een functie voor het verwerken van een array vergat je de parameters van @_ naar lokale variabelen te kopiëren. Als gevolg hiervan leidde wijziging van de lokale variabele tot wijziging van de originele array, wat bugs in andere delen van het programma veroorzaakte.
Voordelen:
Nadelen:
** Positieve case
In het team werd de praktijk ingevoerd van verplichte destructurering van @_ aan het begin van elk subprogramma, en grote objecten worden alleen via referentie doorgegeven.
Voordelen:
Nadelen: