Ich habe mich heute mal mit dem lvalue Attribute auseinander setzen müssen und einige Unstimmigkeiten festgestellt.
- Es macht einen Unterschied, ob man einen Rückgabewert implizit oder explizit liefert. Implizit, also einfach der letzte Wert der Methode, funktioniert für lvalue. Explizit, also mit return, funktioniert nicht. Return legt wohl generell eine Kopie der Rückgabevariablen an, denn bei dem unten stehenden Code wird mit return der Wert der Variablen nie gesetzt. Es wird aber auch kein Fehler geworfen. Dieser Unterschied erklärt auch, warum das implizite return bei Lasttests um ein vielfaches schneller ist. Für die Erbsenzähler 🙂 das liegt im unteren µs Bereich, Für normale Programmierarbeiten also uninteressant.
- Beim Dekorieren einer lvalue-Methode kann kein goto SUBREF verwendet werden. Dort gibt es eine Fehlermeldung, dass eben dieses goto nicht umgebogen werden kann, wobei goto in der Form ja einfach den Kontext wechselt und an der anderen Stelle weiter macht. Was also passiert da im Hintergrund? Und: will ich das wirklich wissen oder kann ich danach nie mehr ruhig schlafen?
- Die Stelle, die die goto-Fehlermeldung wirft, ist entweder zu dumm oder zu schlau. Nach einem solchen goto wird ja in den Kontext der angegebenen Methode gewechselt und ALLE Codezeilen nach diesem goto werden nicht mehr ausgeführt. Wenn ich in die lvalue-Methode aber ein return nach dem goto setze oder irgend einen impliziten Rückgabewert, dann meckert er nicht und alles Funktioniert, wie es soll. Ich traue mich einfach nicht, in den C-Code zu sehen… *grusel*
- Die Art des Wertes, den die lvalue-Methode liefert spielt ja eine Rolle. Es muss zwingend eine änderbare Variable, also z.B. $text und NICHT ‚text‘, sein. Das ist ja verständlich, da dieser Variablen ja ein Wert zugewiesen werden soll. Ein undef liefert auch eine Fehlermeldung. Ein return undef; oder return (); geht aber wieder. Was liegt da für ein Code dahinter, dass das so merkwürdig reagiert? Vielleicht wird ja bei explizitem return alles in eine temporäre Variable gesetzt, aber wozu? Fragen über Fragen…
- Noch so nebenbei, weil ich dadurch einige Zeit nach einem Fehler gesucht habe: in der MODIFY_CODE_ATTRIBUTES Methode, mit der Attribute selber definiert und behandelt werden können, kommen Perl-Interne Attribute, also z.B. lvalue, nie an.
Hier mal ein Code-Beispiel für die ersten zwei beschriebenen Verhaltensweisen:
use strict;
use warnings;
use Test::More 'no_plan';
our $bar;
sub foo : lvalue {
$bar;
#return $bar; # Uncomment this line will result in an error (1)
}
sub bar : lvalue {
goto &foo;
die 'ha!'; # never reached
return;# Remove this will raise an error (2 + 3)
}
is(bar() = 'baz', 'baz', 'set');
is(bar(), 'baz', 'get');
Und eine letzte Frage: gibt es irgendwo eine detaillierte Doku dazu oder ist es wie mit PerlXS ala „wurschtel dich halt durch“?