Wird per Perl eine Kopie zugewiesen?

8

Wird die Zuweisung zu pos in einer Zeichenkette als "write" gezählt, wodurch eine Kopie ausgelöst wird? (Getestet mit Perl 5.26 unter OS X)

Ich schreibe ein kleines Lexing-Dienstprogramm. Eines der Dinge, die häufig auftauchen, ist die Suche nach einem Muster, das bei einem gegebenen Offset beginnt ... und das Zurückgeben des übereinstimmenden Strings, falls es einen gibt.

Um den wiederholten Versuch, ein Token zu konsumieren, zu unterstützen, muss ich die pos direkt nach der Übereinstimmung setzen, wenn wir erfolgreich sind, und an den Ort, wo wir die Suche begonnen haben wenn wir nicht sind.

z.B.

%Vor%

Hier ist eine Implementierung, die das Richtige zurückgibt, aber die Pos nicht korrekt setzt.

%Vor%

Hier ist ein Beispieltest aus der Testsuite für das Modul

%Vor%

Es schlägt mit der folgenden Meldung fehl (ein anderer Test schlägt fehl):

%Vor%

Ich kann das beheben, indem ich stattdessen eine String-Referenz übergebe und die API leicht ändere. Hier ist die neue Implementierung für die Vollständigkeit.

%Vor%

Also, was ist hier los? Warum wird die Zuordnung zu pos(...) nicht auf den ursprünglichen Wert zurückgesetzt, wenn ich nicht eine Referenz verwende?

    
Gregory Nisbet 26.09.2017, 04:12
quelle

1 Antwort

11
  

Hat Perl die Möglichkeit, eine Kopie auszulösen?

Perl 5.20 führte einen Copy-on-Write-Mechanismus ein, der es erlaubt, dass Skalare einen String-Puffer teilen.

Nein, das Ändern von pos($str) löst keine Kopie aus.

%Vor%

[Leere Zeilen wurden zur besseren Lesbarkeit hinzugefügt.]

Wie durch das IsCOW -Flag angezeigt, teilt $_ seinen Zeichenfolgenpuffer ( PV ) mit einem anderen Skalar (der Konstante). Die Zuweisung zu pos ändert das nicht. Das Anfügen an $_ bewirkt andererseits, dass der Zeichenfolgenpuffer kopiert wird ( 0x19551400x1962360 und IsCOW flag ist verloren).

  

Warum wird die Zuweisung zu pos(...) nicht auf den ursprünglichen Wert zurückgesetzt, es sei denn, ich verwende eine Referenz?

Weil es wirklich schlecht wäre, wenn eine Variable ( $str ) eine andere Variable geändert hätte ( $string )! Dass sie sich einen String-Puffer teilen, ist ein irrelevantes Implementierungsdetail.

Das heißt, Perl geht als Referenz, also ist $_[0] ein Alias ​​für $string (das Argument), also würde die Zuweisung an pos($_[0]) sowohl pos($_[0]) als auch pos($string) (die gleiche Variable) ändern.

    
ikegami 26.09.2017, 04:26
quelle

Tags und Links