Hallo Semjon,
Deine „do NOT use prototypes in Perl“-Anmerkung verstehe ich
(noch) nicht (und Mike sicher auch nicht …).
sub foo ($);
"Perl takes the prototype as an indication that
you would like the array automatically converted to a
scalar, and passes the number of elements in the array
to foo().
Das Argument passt aber nicht auf unseren konkreten
Fall, wir erwarten keinen Skalar, sondern eine Liste
im Prototypen
sub foo (@);
In unserem Fall sehe ich bei dem Prototypen kein Problem,
wenn ich einen Skalar übergebe - er wird einfach als Liste
mit einem Element behandelt.
Die implizite Listenkonvertierung ist in den
meisten Fällen unerwünscht, im besten Falle
nur eine Verschwendung von Rechenzeit.
Da gebe ich Dir recht, nur ist das auch kein
Problem, welches durch die Verwendung von Prototypen
entsteht, sondern wie die Funktion an sich arbeitet.
Dein Beispiel kann ich ohne weiteres mit
sub addLine(@@)
{
my $r_data = shift;
push @$r_data, @_;
}
&addLine( @dataArray, @newLine );
&addLine( @dataArray, @newLine );
&addLine( @dataArray, @newLine );
aufrufen.
Wüsstest Du aus dem Kopf, was dann jeweils in der Funktion
ankommt? Oder was Perl meint, was es aus dem Ankommenden macht?
Nun, bei den Perl-Prototypen muss man vorher genau(!) die Doku
lesen, um die Zeile
sub addLine(\@@)
richtig zu verstehen, siehe http://www.perl.com/doc/manual/html/pod/perlsub.html….
Erkenntnisse:
(1) Bedeutung des Prototyps @
bedeutet demnach, dass die Funktion als erstes Argument ein echtes Array
(der Backslash weist auf das literale Zeichen „@“ hin) erwartet, welches
aber in der Funktionsargumentliste @_ von Perl als Arrayreferenz(!) abgelegt
wird.
(2) Bedeutung des Prototyps @
bedeutet, dass alle restlichen Argumente wie sie sind in die Argumentliste
wandern.
(3) Prototyp-Deaktivierung
„Old-School-Funktionsaufrufe“ mit führendem „&“ hebeln die Prototypprüfung aus.
Insofern sind Deine Beispiele der Form
&addLine( @dataArray, @newLine );
für das Testen von Prototypen wenig hilfreich.
Mit dem folgenden Wissen gewappnet, lassen sich Deine 3 korrigierten Versionen
kommentieren
Bsp. 1:
addLine( @dataArray, \@newLine );
Das nach (1) erwartete Array wird korrekt übergeben und
ihm eine Arrayreferenz angehängt. Wohl nicht das, was eigentlich
bezweckt war.
Bsp. 2:
addLine( \@dataArray, @newLine );
Ist ein Fehler, da nach (1) als erstes Argument
ein echtes Array erwartet wird. Perl erkennt das
natürlich auch und meckert:
Type of arg 1 to main::addLine must be array (not reference constructor)
Hier hat der Prototyp seine Funktion also voll und ganz erfüllt, indem er einen
Programmierfehler mit einem sofortigen, klaren Programmabruch quittiert - ein
Fehler weniger.
Bsp. 3:
addLine( @dataArray, @newLine );
Das erwartete Array im ersten Argument wird übergeben und
danach alle Folgeargumente hinten angehängt. Also das, was
Mike eigentlich wollte.
Alles in allem halte ich Perl-Prototypen für eine feine Sache.
Ihre Einführung wurde von den schlauen Perl-Entwicklern aus gutem
Grund gemacht.
Gruß,
-Andreas.