ProgrammatieFull Stack Perl Developer

Welke methoden voor het doorgeven van argumenten aan subprogramma's bestaan er in Perl en hoe organiseer je het doorgeven per referentie? Wat zijn de nuances van het werken met @_ en wanneer is doorgeven per referentie noodzakelijk?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Perl gebeurt alle argumentatie van functies via de array @_. Bij het aanroepen van een subprogramma komen alle doorgegeven parameters binnen in deze array, en in eerste instantie is dit een lijst, en geen kopie, dus als je $_[0] verandert, wijzig je het origineel.

Doorgeven per waarde:

sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # Alleen de lokale variabele verandert }

Doorgeven per referentie:

sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data is nu (1,2,3,42)

Nuances:

  • Als je de originele array of hash wilt wijzigen — geef dan een referentie door.
  • Gewone variabelen ($foo, $bar) binnen @_ zijn aliassen van de originele argumenten, maar bij het uitpakken via my ($a, $b) = @_ worden er kopieën gemaakt.
  • Voor arrays en hashes wordt bij gewone overdracht de inhoud in een lijst uitgepakt, en verlies je de grenzen: je moet een referentie doorgeven of de specificiteit van shifts gebruiken.

Valkuilvraag

Als je in Perl een functie het array zo doorgeeft: myfunc(@arr), en binnen de functie aanspreekt tot $_[0], wat zit daar dan in?

Juist antwoord: Daar zit het eerste element van de waarde van de array, en niet de referentie naar de hele array! Om een array als een geheel object door te geven, gebruik je een referentie: myfunc(\@arr).

Voorbeeld:

sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # Geeft 'foo' weer, en geen referentie naar de array print_first(\@a); # Geeft ARRAY(0x...) weer — verwijzing naar de hele array

Geschiedenis

In een van de projecten werd een functie zo aangeroepen om een globale hash te wijzigen: update_hash(%global). Binnen werd $_[0] gewijzigd. Het resultaat — alleen een lokaal deel van de array van argumenten werd gewijzigd, terwijl de globale hash niet werd aangepast. De correcte oplossing was het doorgeven van een referentie: update_hash(\%global).

Geschiedenis

Bij het schrijven van een API-framework werden aan functies vaak veel benoembare argumenten doorgegeven, met behulp van een hash. Soms werd een array doorgegeven (maar geen referentie!), en de argumenten "vermengden" zich, wat tot verwarring leidde: myfunc(@arr, %opts). Het bleek dat een deel van de hash-sleutels werd vervangen door de waarden van de array, en het was moeilijk om de fout te ontdekken.

Geschiedenis

Bij de implementatie van recursieve doorloop van een boom wilden ze interne elementen wijzigen. Arrays werden "zoals ze zijn" doorgegeven, niet per referentie. Ze maakten kopieën, en wijzigingen hadden geen invloed op de externe context. Het probleem werd opgelost door de overdrachten te vervangen door de referentiestijl.