Subroutinen definieren
Argumente landen im Array @_. Der Rückgabewert ist der letzte ausgewertete Ausdruck (oder return).
use strict; use warnings;
sub gruss {
my ($name, $anrede) = @_;
$anrede //= "Hallo";
return "$anrede, $name!";
}
sub summe {
my $s = 0;
$s += $_ for @_; # beliebig viele Argumente
return $s;
}
sub minmax {
my @sortiert = sort { $a <=> $b } @_;
return ($sortiert[0], $sortiert[-1]); # mehrere Werte
}
sub optionen {
my (%opt) = (farbe => "blau", groesse => 10, @_); # benannte Argumente mit Standardwerten
return join(", ", map { "$_=$opt{$_}" } sort keys %opt);
}
print gruss("Mia"), "\n";
print gruss("Tom", "Hi"), "\n";
print summe(1, 2, 3, 4), "\n";
my ($klein, $gross) = minmax(5, 2, 9, 1);
print "$klein $gross\n";
print optionen(groesse => 20, rahmen => "ja"), "\n";
print "Argumente: ", scalar(@{[ 1, 2, 3 ]}), "\n";Hallo, Mia! Hi, Tom! 10 1 9 farbe=blau, groesse=20, rahmen=ja Argumente: 3
Seit Perl 5.36 gibt es Signaturen:
use v5.36; # aktiviert strict, warnings, say und Signaturen
sub addiere($x, $y = 10) { return $x + $y }
say addiere(1);
say addiere(1, 2);
sub ersten_und_rest($erster, @rest) { return "$erster | @rest" }
say ersten_und_rest(qw(a b c));
sub mit_hash($name, %opt) { "$name: " . join(",", map {"$_=$opt{$_}"} sort keys %opt) }
say mit_hash("x", b => 2, a => 1);11 3 a | b c x: a=1,b=2
say ist wie print, hängt aber automatisch einen Zeilenumbruch an.
Kontext: wantarray
Eine Funktion kann prüfen, ob sie in Listen- oder Skalarkontext aufgerufen wird:
use v5.36;
sub kontext {
return wantarray ? "Liste" : defined(wantarray) ? "Skalar" : "void";
}
my @l = kontext();
my $s = kontext();
kontext();
say "$l[0] $s";Liste Skalar
Referenzen auf Funktionen und Closures
use v5.36;
my $quadrat = sub ($x) { $x * $x }; # anonyme Funktion
say $quadrat->(7);
sub zaehler_erzeugen($start = 0) {
my $n = $start;
return {
plus => sub { ++$n },
minus => sub { --$n },
wert => sub { $n },
};
}
my $z = zaehler_erzeugen(10);
$z->{plus}->() for 1..3;
$z->{minus}->();
say $z->{wert}->();
sub wende_an($f, @liste) { map { $f->($_) } @liste }
say join ",", wende_an(sub ($x) { $x * 10 }, 1, 2, 3);
my %dispatch = (hallo => sub { "Hallo!" }, tschuess => sub { "Tschüss!" });
say $dispatch{hallo}->();
my $ref = \&wende_an;
say ref($ref);49 12 10,20,30 Hallo! CODE
Closures merken sich die Variablen ihrer Umgebung ($n oben).
Rekursion und Variablen-Gültigkeit
use v5.36;
sub fakultaet($n) { $n <= 1 ? 1 : $n * fakultaet($n - 1) }
sub fib($n) { $n < 2 ? $n : fib($n - 1) + fib($n - 2) }
say fakultaet(15);
say join " ", map { fib($_) } 0..12;
our $global = "global"; # Paketvariable
my $lexikalisch = "außen";
sub test {
my $lexikalisch = "innen"; # verdeckt die äußere
return "$lexikalisch $global";
}
say test();
say $lexikalisch;
{
local $global = "lokal überschrieben";
say test();
}
say test();1307674368000 0 1 1 2 3 5 8 13 21 34 55 89 144 innen global außen innen lokal überschrieben innen global
Nutze my (lexikalisch, im Block gültig). our deklariert Paketvariablen, local überschreibt sie temporär (selten nötig).
Merke
- Argumente in
@_, kopiere sie mitmy (...) = @_; returnist optional, mehrere Werte als Liste- Signaturen (
sub f($x, $y = 1)) undsaymituse v5.36; - Anonyme Subs
sub {...}, Referenzen\&f, Aufruf$ref->(...) wantarrayerkennt den Kontext; Closures merken sich Variablen
Aufgabe
Schreibe eine Funktion statistik(@zahlen), die Summe, Mittelwert und Maximum als Hash zurückgibt.