In einer anderen Frage zum Stapelüberlauf behauptete Leon Timmermans :
Ich würde Ihnen raten, keine Prototypen zu verwenden. Sie haben ihre Verwendung, aber nicht für die meisten Fälle und definitiv nicht in dieser.
Warum könnte dies wahr sein (oder anders)? Ich liefere fast immer Prototypen für meine Perl-Funktionen, und ich habe noch nie jemanden gesehen, der etwas Schlechtes über ihre Verwendung gesagt hat.
Antworten:
Prototypen sind nicht schlecht, wenn sie richtig verwendet werden. Die Schwierigkeit besteht darin, dass Perls Prototypen nicht so funktionieren, wie es die Leute oft erwarten. Personen mit einem Hintergrund in anderen Programmiersprachen erwarten in der Regel, dass Prototypen einen Mechanismus zur Überprüfung der Richtigkeit von Funktionsaufrufen bereitstellen: Das heißt, sie haben die richtige Anzahl und Art von Argumenten. Perls Prototypen sind für diese Aufgabe nicht gut geeignet. Es ist der Missbrauch , der schlimm ist. Perls Prototypen haben einen einzigartigen und ganz anderen Zweck:
Mit Prototypen können Sie Funktionen definieren, die sich wie integrierte Funktionen verhalten.
Sie können beispielsweise eine Funktion wie die folgende definieren:
und nenne es als
ohne dass Sie das schreiben müssen
\
, um einen Verweis auf das Array zu erhalten.Kurz gesagt, mit Prototypen können Sie Ihren eigenen syntaktischen Zucker herstellen. Das Moose-Framework verwendet sie beispielsweise, um eine typischere OO-Syntax zu emulieren.
Dies ist sehr nützlich, aber die Prototypen sind sehr begrenzt:
Unter Prototypen in Perlsub finden Sie alle wichtigen Details.
quelle
Das Problem ist, dass Perls Funktionsprototypen nicht das tun, was die Leute denken. Sie sollen es Ihnen ermöglichen, Funktionen zu schreiben, die wie die integrierten Funktionen von Perl analysiert werden.
Erstens ignorieren Methodenaufrufe Prototypen vollständig. Wenn Sie OO-Programmierung durchführen, spielt es keine Rolle, welchen Prototyp Ihre Methoden haben. (Sie sollten also keinen Prototyp haben.)
Zweitens werden Prototypen nicht strikt durchgesetzt. Wenn Sie eine Unterroutine mit aufrufen
&function(...)
, wird der Prototyp ignoriert. Sie bieten also keine wirkliche Sicherheit.Drittens sind sie gruselig auf Distanz. (Insbesondere der
$
Prototyp, bei dem der entsprechende Parameter im skalaren Kontext anstelle des Standardlistenkontexts ausgewertet wird.)Insbesondere erschweren sie die Übergabe von Parametern aus Arrays. Beispielsweise:
Drucke:
zusammen mit 3 Warnungen über
main::foo() called too early to check prototype
(wenn Warnungen aktiviert sind). Das Problem ist, dass ein im skalaren Kontext ausgewertetes Array (oder Array-Slice) die Länge des Arrays zurückgibt.Wenn Sie eine Funktion schreiben müssen, die sich wie eine integrierte Funktion verhält, verwenden Sie einen Prototyp. Verwenden Sie andernfalls keine Prototypen.
Hinweis: Perl 6 wird komplett überarbeitet und sehr nützliche Prototypen haben. Diese Antwort gilt nur für Perl 5.
quelle
foo()
Ausdrucken 2, da dies das letzte Element in Ihrem Slice mit zwei Elementen ist. Wechseln Sie zumy @array = qw(foo bar baz)
und Sie werden den Unterschied sehen. (Abgesehen davon initialisiere ich Arrays / Listen aus diesem Grund nicht mit 0- oder 1-basierten numerischen Sequenzen in wegwerfbarem, demonstrativem Code. Die Verwirrung zwischen Indizes, Zählungen und Elementen in Kontexten hat mich mehr als einmal gebissen.a b c
, um Ihren Standpunkt klarer zu machen.Ich stimme den beiden oben genannten Postern zu. Im Allgemeinen
$
sollte die Verwendung vermieden werden. Prototypen sind nur dann sinnvoll , wenn der Block Argumente (&
), Klümpchen (*
) oder Referenzprototypen (\@
,\$
,\%
,\*
)quelle
($)
Prototyp einen benannten unären Operator, der nützlich sein kann (sicherlich findet Perl sie nützlich; ich habe gelegentlich auch). Zweitens sollten Sie sich beim Überschreiben von integrierten Funktionen (ob durch Import oder Verwendung von CORE :: GLOBAL: :) im Allgemeinen an den Prototyp halten, den die integrierte Version enthält, auch wenn dies eine enthält$
, oder Sie könnten den Programmierer (sich selbst) überraschen. gerade) mit Listenkontext, in dem der integrierte Kontext sonst einen skalaren Kontext bereitstellen würde.Einige Leute, die sich einen Perl-Subroutinen-Prototyp ansehen, denken, dass dies etwas bedeutet, was es nicht bedeutet:
Für Perl bedeutet dies, dass der Parser zwei Argumente erwartet. Auf diese Weise können Sie mit Perl Unterprogramme erstellen, die sich wie integrierte Funktionen verhalten und alle wissen, was Sie vom nachfolgenden Code erwarten können. Sie können über Prototypen in Perlsub lesen
Ohne die Dokumentation zu lesen, vermuten die Leute, dass sich die Prototypen auf die Überprüfung von Laufzeitargumenten oder etwas Ähnliches beziehen, das sie in anderen Sprachen gesehen haben. Wie bei den meisten Dingen, die Leute über Perl erraten, erweisen sie sich als falsch.
Ab Perl v5.20 verfügt Perl jedoch über eine experimentelle Funktion, die experimentell ist, wenn ich dies schreibe, und die eher das bietet, was Benutzer erwarten und was. Perls Subroutinensignaturen zählen Laufzeitargumente, Variablenzuweisungen und Standardeinstellungen:
Dies ist die Funktion, die Sie wahrscheinlich wünschen, wenn Sie Prototypen in Betracht ziehen.
quelle