Ich rufe eine Subroutine auf mit subr(%hashtab, $par).
In der Subroutine habe ich
my (%tab, $p) = @_;
So und jetzt nochmal eine etwas ausführlichere Erklärung, damit man auch sieht das Norbert hier falsche Sachen erzählt hat.
use strict;
use Data::Dumper;
my %hash = ( k1 => 'wert1', k2 => 'wert2');
my $skalar = 'parameter';
sub test_prototype (\% $);
test(%hash, $skalar);
test(\%hash, $skalar);
test_prototype(%hash, $skalar);
sub test{
warn "\ncall: test(@_) =" .(scalar @_) ." Parameter\n";
my(%lokal, $leer) = @_;
print '%lokal=', Dumper \%lokal;
print '$leer=', Dumper $leer;
}
sub test_prototype (\% $){
warn "\ncall: test_prototype(@_) =" .(scalar @_) ." Parameter\n";
my($lokal, $leer) = @_;
my %lokal = %$lokal;
print '%lokal=', Dumper \%lokal;
print '$leer=', Dumper $leer;
}
Das Skript zeigt, wie Perl die Parameter übergibt, wie man diese annehmen kann und das Perl durchaus eine Warnungen ausgibt, wenn man diese falsch zuweist. Auch habe ich die von Alexander erwähnte Lösung in der Funktion test_protoptye eingebaut. Die Ausgabe sieht so aus:
call: test(k2 wert2 k1 wert1 parameter) =5 Parameter
Odd number of elements in hash assignment at t.pl line 15.
%lokal=$VAR1 = {
'parameter' => undef,
'k2' => 'wert2',
'k1' => 'wert1'
};
$leer=$VAR1 = undef;
call: test(HASH(0x225b34) parameter) =2 Parameter
%lokal=$VAR1 = {
'HASH(0x225b34)' => 'parameter'
};
$leer=$VAR1 = undef;
call: test_prototype(HASH(0x225b34) parameter) =2 Parameter
%lokal=$VAR1 = {
'k2' => 'wert2',
'k1' => 'wert1'
};
$leer=$VAR1 = 'parameter';
Die Hash-Tabelle ist in Ordnung, $p ist leer (obwohl $par einen Wert besitzt).
Wenn das wirklich so ist und die Warnungen eingeschaltet ist muss die Warnung ausgegeben worden sein:
Odd number of elements in hash assignment at t.pl line 15.
Der Grund dafür ist, das ein Hash im Prinzip nichts weiter als ein Array ist und folglich wird eine Zuweisung in der Form:
%hash = (@array, $skalar, %hash);
Alle auf der rechten Seite vorhandenen Werte dem auf der linken Seite stehenden Hash zuweisen.
Wenn jetzt auf beiden Seiten eine Liste steht:
(%hash, $skalar, $nocheinskalar) = ( ...);
Wird der Hash links, trotzdem alle Werte in der rechten Liste aufnehmen. Das ist kein Verhalten das man abstellen kann sondern ein Feature in Perl, dass durchaus logisch und nützlich ist (ausser wenn man es nicht verstehen will).
Wenn man weiß und versteht das es so ist, dann wird man schnell auf den Trichter kommen, dass es fast immer sinnvoller ist, wenn man irgendeine Form eines Array hat, dieses als Referenz an eine Funktion zu übergeben, was nicht nur das Parameterhandling vereinfacht sondern darüber hinaus auch Speicher spart und schneller ist. Möchte man eine lokale Kopie muss dies halt explizit gesagt werden.
Struppi.