Warum sollten Sie NICHT ein array zurückgeben, ref?
In der Frage "Wieder ein ganzes array aus einem Perl-subroutine ineffizient" zwei Personen empfohlen, vor der Optimierung, wenn es keine Notwendigkeit für Sie. Als eine Allgemeine Regel, die Optimierung kann die Komplexität, und wenn es nicht mehr benötigt, einfach besser. Aber in diesem speziellen Fall der Rückgabe ein array oder ein array, ref, ich sehe nicht, dass es irgendeine zusätzliche Komplexität, und ich denke, dass die Konsistenz im interface-design wäre wichtig. Folglich habe ich fast immer etwas zu tun:
sub foo
{
my($result) = [];
#....build up the result array ref
$result;
}
Gibt es einen Grund, ich sollte das nicht tun, ist auch für kleine Ergebnisse?
- In "my($Ergebnis) = [];",, warum die Klammern?
- Wieder, für Konsistenz Willen, ich Tue immer mein($foo); my($bar, $baz); ich nie tun 'my $foo', weil dann einige meiner "mein ' s" in einem skalarkontext und einige sind in einer Liste Kontext. Damit habe ich manchmal meine($cnt) = scalar(@array); dessen bin ich mir sicher, würden einige Leute verrückt....
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollte man nicht ein array zurückgeben, Referenz, wenn es inkonsistent mit dem rest der Oberfläche. Wenn alles, was Sie arbeiten mit Renditen Listen anstatt von Referenzen, nicht die ungeraden Ente, die bewirkt, dass andere Programmierer sich daran zu erinnern die Ausnahme.
Es sei denn, Sie haben große Listen, das ist wirklich ein micro-Optimierungs-Problem. Sollten Sie so glücklich sein werden, wenn dies der Engpass in Ihrem Programm.
Soweit Komplexität geht, ist der Unterschied zwischen einer Referenz und einer Liste so weit unten auf der Skala Komplexität, dass Sie größere Probleme haben, wenn Ihre Programmierer das schwer fällt. Komplizierte algorithmen und workflows sind Komplex, aber das ist nur syntax.
Having said all das, ich Neige dazu, alles zurück Verweise und Schnittstellen im Einklang mit, dass.
Nicht. Außer tun "return $result;" für Klarheit.
Ich erinnere mich an die Prüfung der Effizienz und der performance-Unterschied war minimal für kleine arrays. Für große arrays, die einen Verweis war viel schneller.
Es ist wirklich eine Komfort-Sache für das kleine Ergebnis. Würden Sie lieber tun:
Oder Rückgabe einer Referenz:
Einen anderen Weg für die Rückgabe einer Referenz:
Regel, sobald Sie sich entscheiden, welchen Weg zu gehen, halten Sie sich nur an für Sie Modul, da es macht es verwirrend, wechseln von einer Methode zur nächsten.
Ich in der Regel Rückgabe-array von Referenzen auf Listen von ähnlichen Dingen, und ein array, wenn die Antwort besteht aus zwei bis vier verschiedenen Elementen. Mehr als das, ich mache einen hash, da nicht alle Aufrufer kümmert sich um alle response-Elemente.
($foo, $bar) = @{barbaz()}
Werde ich kopiere den relevanten Teil meiner Antwort aus die andere Frage hier.
Die oft übersehen zweite überlegung ist die Schnittstelle. Wie ist das zurückgegebene array verwendet werden? Dies ist wichtig, weil die gesamte array-Dereferenzierung wird ein bisschen scheußlich in Perl. Zum Beispiel:
Dass ist hässlich. Das ist viel besser.
Es eignet sich auch zur Kartierung und grepping.
Aber wieder ein array ref kann nützlich sein, wenn Sie gehen, herausgreifen einzelnen Elemente:
Dass ist einfacher als:
Oder:
Aber an diesem Punkt, sollten Sie sich die Frage, ob @info ist wirklich eine Liste oder einen hash.
Im Gegensatz zu arrays vs-array-refs, es gibt wenig Grund, Sie wieder ein hash über eine hash-ref. Hash-Referenzen erlauben, praktisch, kurzer hand, wie der code oben. Und gegenüber von arrays vs refs, macht es den iterator Fall einfacher, oder zumindest verhindert, dass ein Mitte-Mann-variable.
Was Sie nicht tun sollten ist haben
getInfo()
ein array zurückgeben, ref im skalaren Kontext und eine Reihe in der Liste Kontext. Diese muddles die traditionelle Verwendung von skalaren Kontext als array-Länge, die den Benutzer überraschung.Ich möchte hinzufügen, dass, während alles macht durchweg X ist eine gute Faustregel, es ist nicht von überragender Bedeutung bei der Gestaltung eines guten interface. Gehen Sie ein bisschen zu weit mit ihm, und Sie können leicht steamroll andere wichtige Anliegen.
Schließlich will ich meine plug-eigenen Modul, Method::Signatures, denn es bietet einen Kompromiss für die übergabe von array-Referenzen, ohne dass das array ref-syntax.
Dies geschieht durch die Magie der Daten::Alias.
Da niemand erwähnt überwantarray
werde ich 🙂Halte ich für eine gute Praxis, lassen Sie die Anrufer entscheiden welchem Kontext Sie will das Ergebnis. Zum Beispiel, im code unten, Fragen Sie perl für den Kontext die subroutine aufgerufen wurde, und entscheiden, was Sie zurück.
Dann
und
funktioniert richtig, weil die Liste Kontext, und:
zurückkehren wird, die array-Referenz.
Weitere Infos über
wantarray
möchten Sie vielleicht, umperldoc -f wantarray
.Edit: ich über-sehenden eine der ersten Antworten, die die bereits erwähnten
wantarray
, aber ich denke, das ist Antwort ist immer noch gültig, weil es macht es ein wenig klarer.Wenn das array aufgebaut ist, in der Funktion gibt es keinen Grund zu return array; einfach nur wieder eine Referenz, da der Anrufer gewährleistet ist, dass es nur ein Exemplar (es wurde gerade erstellt).
Wenn die Funktion über eine Reihe von globalen arrays und die Rückkehr einer von Ihnen, dann ist es akzeptabel, um wieder eine Referenz, wenn der Anrufer nicht ändern. Wenn der Anrufer möglicherweise ändern Sie das array, und das ist nicht gewünscht, dann ist die Funktion zurückgeben sollte eine Kopie.
Dies ist wirklich eine einzigartige Perl-problem. In Java Sie immer wieder eine Referenz, und die Funktion verhindern, dass das array geändert wird (wenn das Ihr Ziel ist) durch das finalisieren das array und die Daten, die es enthält. In python Referenzen zurückgegeben werden und es gibt keine Möglichkeit zu verhindern, dass Sie geändert werden; wenn das wichtig ist, eine Referenz auf eine Kopie zurückgegeben wird, statt.
Ich will einfach nur einen Kommentar auf die Idee, über unbeholfene syntax für die Abwicklung einer array-Referenz im Gegensatz zu einem Liste. Als brian erwähnt, sollten Sie wirklich nicht tun, wenn der rest des Systems ist mithilfe von Listen. Es ist eine unnötige Optimierung in den meisten Fällen.
Wenn das allerdings nicht der Fall, und Sie sind frei, zu erstellen Sie Ihren eigenen Stil, dann eine Sache, die machen die Codierung weniger stinkend ist mit autobox.
autobox
drehtSCALAR
,ARRAY
undHASH
(sowie andere) in "Pakete", so dass Sie kann code:anstelle der etwas mehr ungeschickt:
durch die Kodierung so etwas wie dieses:
Beachten Sie, dass
autobox
erfordert, dass Sie alle implementieren das Verhalten, die Sie wollen, aus diesen.$arr_ref->pop()
funktioniert nicht, bis Sie definierensub ARRAY::pop
es sei denn, Sie verwenden autobox::Core$obj->get_arrayref->@[0,1]
um die Scheibe. Ich finde es wirklich praktisch.Ich glaube nicht, dass Sie sollten das Gefühl gezwungen, nur mit einer oder zwei Methoden. Sie sollten jedoch konsistent halten für jedes Modul oder der Module zu setzen.
Hier sind einige Beispiele zum nachdenken:
Kann ich sehen, möglicherweise verwenden viele von diesen in der Zukunft Projekt, aber einige von Ihnen sind eher sinnlos.
Einen wichtigen Auslassungen in den oben genannten Antworten: nicht wieder Verweise auf private Daten!
Beispiel:
Ja, die Benutzer können peek direkt unter die Haube mit Perl-Objekten implementiert diese Weise aber nicht machen es einfach für die Nutzer unwissentlich Schießen selbst in den Fuß, z.B.,
Besser wäre, um wieder eine (vielleicht zu tief) kopieren Sie Ihre privaten Daten, wie in
Sind, wenn Sie verwendet werden, um code als erstes snippet in Mathieu Longtin Antwort Sie haben zu schreiben, hässlich-code als zweite snippet oder diese nicht so viel besseren code:
Ich denke, dies ist der größte Nachteil bei der Rückkehr Referenz anstelle von array. Wenn ich will zurück kleine Menge von verschiedenen Arten Werte. Ich bin zum Rückgabe-array und weisen direkt auf die Variablen (wie früher in Python zum Beispiel).
Wenn die Menge der Werte ist größer, und verschiedene Art, die ich verwendet, um zurück hash-ref (besser für die Umgestaltung)
Wenn die return-Werte sind von der gleichen Art, als die Rückkehr von array oder array-ref ist fraglich, je nach Menge.
Ich bin nicht sicher, ob die Rückkehr eine Referenz ist in diesem Fall effizienter; D. H. ist in Perl kopieren zurückgegebenen Daten durch Unterprogramme?
Im Allgemeinen, wenn dein array aufgebaut ist, vollständig innerhalb des Unterprogramms, dann gibt es keine offensichtliche problem mit der Rückgabe einer Referenz, da sonst das array wäre sowieso verworfen. Allerdings, wenn der Verweis ist auch bestanden woanders zurückgeben können, haben Sie möglicherweise zwei Kopien der gleichen Referenz-und Sie kann geändert werden, in einem Ort, aber nicht zu erwarten, dass anderswo.
Gibt es einen Grund, ich sollte das nicht tun, ist auch für kleine Ergebnisse?
Gibt es kein perl-spezifischen Grund, Sinn es ist richtig und effizient für die Rückgabe einer Referenz auf das lokale array. Der einzige Nachteil ist, dass Menschen, die die Funktion aufrufen zu tun haben, ist den zurückgegebenen array, ref, und Zugriff auf Elemente mit dem Pfeil
->
oder dereferenzieren etc. So, es ist ein wenig mehr lästig für den Anrufer.Rückgabe eines array gibt einige schöne Vorteile:
Wenn Sie return array refs, haben Sie zu schreiben, mehrere subs, um die gleiche Arbeit tun. Auch ein leeres array zurückgibt false in einem booleschen Kontext, aber ein leeres array ref nicht.
Wenn Sie return array refs, dann haben Sie zu tun:
Außer wenn get_array_ref() nicht zurück, ein ref, sprich statt und undef, Wert, Sie haben ein Programm-Absturz aufzuhalten. Eine der folgenden helfen:
So, wenn der speed-Leistungen erforderlich sind, oder wenn Sie eine array-ref (vielleicht möchten Sie ermöglichen die direkte manipulation eines Objekts collection-element--pfui, aber manchmal muss es geschehen), gibt ein array zurück. - ref. Ansonsten find ich die Vorteile von standard-arrays zu bewahren.
Update: Es ist wirklich wichtig zu erinnern, dass das, was du bei einer Rücksendung aus einer routine ist nicht immer ein array oder eine Liste. Was Sie zurückgeben, ist das, was folgt, die
return
oder das Ergebnis der letzten operation. Ihr Rückgabewert wird ausgewertet im Kontext. Die meisten der Zeit, wird alles in Ordnung sein, aber manchmal kann man unerwartete Verhalten.Vergleichen mit:
So, wenn Sie sagen, "geben ein array zurück," werden Sie sicher, dass Sie meinen wirklich "ein array zurückgeben". Sich bewusst sein, was Sie nach Ihrer Routinen.