Frage zu Packages und our
Hallo,
ich bin auf ein (zumindest für mich :-) merkwürdiges Verhalten bei
der Verwendung von Packages und "our" gestoßen, das ich mir
nicht erklären kann.
Folgender Code
use strict;
use warnings;
package Alpha;
our $test = 10;
print "Alpha: $test\n";
package Beta;
our $test = 20;
print "Beta: $test\n";
package Alpha;
print "Alpha: $test\n";
liefert dieses Ergebnis:
Alpha: 10
Beta: 20
Alpha 20
Ich hätte eigentlich erwartet, auch beim zweiten Mal für die Alpha-
Variable den Wert 10 zurückgeliefert zu bekommen. Passiert aber
eben nicht.
Irgendwelche Erklärungen?
Schöne Grüße aus Wien,
Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol [at] adv.magwien.gv.at
Re: Frage zu Packages und our
Ferry Bolhar wrote:
> Folgender Code
>
> use strict;
> use warnings;
> package Alpha;
> our $test = 10;
> print "Alpha: $test\n";
> package Beta;
> our $test = 20;
> print "Beta: $test\n";
> package Alpha;
> print "Alpha: $test\n";
>
> liefert dieses Ergebnis:
>
> Alpha: 10
> Beta: 20
> Alpha 20
>
> Ich hätte eigentlich erwartet, auch beim zweiten Mal für die Alpha-
> Variable den Wert 10 zurückgeliefert zu bekommen. Passiert aber
> eben nicht.
Wieso?
Mit our sagst du, dass du die Variabel mit anderen Modulen teilen
willst. D.h. du hast überall das gleiche $test
Struppi.
Re: Frage zu Packages und our
Ferry Bolhar wrote:
> ich bin auf ein (zumindest für mich :-) merkwürdiges Verhalten bei
> der Verwendung von Packages und "our" gestoßen, das ich mir
> nicht erklären kann.
>
> Folgender Code
>
> use strict;
> use warnings;
> package Alpha;
> our $test = 10;
> print "Alpha: $test\n";
> package Beta;
> our $test = 20;
> print "Beta: $test\n";
> package Alpha;
> print "Alpha: $test\n";
>
> liefert dieses Ergebnis:
>
> Alpha: 10
> Beta: 20
> Alpha 20
>
> Ich hätte eigentlich erwartet, auch beim zweiten Mal für die Alpha-
> Variable den Wert 10 zurückgeliefert zu bekommen. Passiert aber
> eben nicht.
>
> Irgendwelche Erklärungen?
Es verhält sich so, wie es definiert ist, siehe perldoc -f our:
An "our" declaration declares a global variable that will be
visible across its entire lexical scope, even across package
boundaries. The package in which the variable is entered is
determined at the point of the declaration, not at the point of
use.
Wenn Du Package-Globals fernab ihrer Deklaration zugreifst,
solltest Du sie immer mit dem Package-Präfix versehen, à la
print "$Alpha::test\n";
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Frage zu Packages und our
J. Strübig wrote:
> Ferry Bolhar wrote:
>
>>Folgender Code
>>
>>use strict;
>>use warnings;
>>package Alpha;
>>our $test = 10;
>>print "Alpha: $test\n";
>>package Beta;
>>our $test = 20;
>>print "Beta: $test\n";
>>package Alpha;
>>print "Alpha: $test\n";
>>
>>liefert dieses Ergebnis:
>>
>>Alpha: 10
>>Beta: 20
>>Alpha 20
>>
>>Ich hätte eigentlich erwartet, auch beim zweiten Mal für die Alpha-
>>Variable den Wert 10 zurückgeliefert zu bekommen. Passiert aber
>>eben nicht.
>
> Wieso?
>
> Mit our sagst du, dass du die Variabel mit anderen Modulen teilen
> willst. D.h. du hast überall das gleiche $test
Das ist nicht richtig. Der Code führt zwei verschiedene
Variable ein, $Alpha::test und $Beta::test.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Frage zu Packages und our
J. Strübig:
> > Ich hätte eigentlich erwartet, auch beim zweiten Mal für die Alpha-
> > Variable den Wert 10 zurückgeliefert zu bekommen. Passiert aber
> > eben nicht.
>
> Wieso?
>
> Mit our sagst du, dass du die Variabel mit anderen Modulen teilen
> willst. D.h. du hast überall das gleiche $test
Dann habe ich sichtlich eine unterschiedliche Interpretation von der
"package" Direktive bzw. vom Einsatz von "our".
Wo steht, dass ich mit "our" eine Variable mit anderen Modulen
teilen möchte? Das führt doch jede durch Namensräume bedingte
Trennung ad absurdum.
Wenn ich "package A" sage, so spreche ich mit "$x" eigentlich $A::x
an, oder nicht? Und daher in "package B" die Variable $B::x, nicht
wahr? Das "our" erlaubt mir ja nur, sie unqualifiziert anzusprechen,
was mir der Compiler sonst mit "use strict" verbieten würde.
Das heißt, in meinen Code sind die beiden "$test" Variablen zwei
unterschiedliche globale Variable, einmal $Alpha::test und einmal
$Beta::test. Wieso bekomme ich also im Alpha-Package den Wert
der Beta-Variable?
LG, Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol [at] adv.magwien.gv.at
"$Beta::test". Daher
Re: Frage zu Packages und our
Frank Seitz:
> Es verhält sich so, wie es definiert ist, siehe perldoc -f our:
>
> An "our" declaration declares a global variable that will be
> visible across its entire lexical scope, even across package
> boundaries. The package in which the variable is entered is
> determined at the point of the declaration, not at the point of
> use.
Ich sehe da keinen Widerspruch - ich deklariere eine Variable
im Package Alpha (daher kommt sie in das Package Alpha)
und eine zweite im Package Beta (daher wird sie Teil des
Packages Beta). Das sind doch zwei verschiedene Variable,
daran besteht ja wohl kein Zeifel, oder? Also sollte ich doch
in dem jeweiligen Package später auch unqualifiziert darauf
zugreifen können, oder nicht? Also mit
package Alpha;
print "$test\n"; # spricht $Alpha::test an
package Beta;
print "$test\n"; # spricht $Beta::test an
Schließlich wurden ja beide Variable deswegen extra im jeweiligen
Package deklariert, und die beiden Deklarationen waren ja auch
ok (zumindest gab es keinen Fehler). Und: lasse ich das "use
strict" und das "our" weg, funktioniert es ja auch wie erwartet,
nur fehlt dann eben das - mancherorts so hoch gelobe - "use strict",
das aber wiederum eben eine solche Deklaration verlangt.
> Wenn Du Package-Globals fernab ihrer Deklaration zugreifst,
> solltest Du sie immer mit dem Package-Präfix versehen, à la
Das ist sicher eine Option, aber ich war bisher der Meinung, dass
dies nicht notwendig sei. Außerdem interessiert mich hier schlicht
und einfach das "Warum" - ich bin nämlich der Ansicht, dass dies
ein Bug ist, solange bis mich jemand eines Besseren belehrt.
Danke aber für deine Antwort, und schöne Grüße aus Wien,
Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol [at] adv.magwien.gv.at
Re: Frage zu Packages und our
Ferry Bolhar wrote:
> Frank Seitz:
>>
>>Es verhält sich so, wie es definiert ist, siehe perldoc -f our:
>>
>> An "our" declaration declares a global variable that will be
>> visible across its entire lexical scope, even across package
>> boundaries. The package in which the variable is entered is
>> determined at the point of the declaration, not at the point of
>> use.
>
> Ich sehe da keinen Widerspruch - ich deklariere eine Variable
> im Package Alpha (daher kommt sie in das Package Alpha)
> und eine zweite im Package Beta (daher wird sie Teil des
> Packages Beta). Das sind doch zwei verschiedene Variable,
> daran besteht ja wohl kein Zeifel, oder?
Nein, daran besteht kein Zweifel.
> Also sollte ich doch
> in dem jeweiligen Package später auch unqualifiziert darauf
> zugreifen können, oder nicht?
Nein, weil dazwischen eine zweite Deklaration kommt, die wegen
visible across its entire lexical scope, even
across package boundaries
ab da gültig ist, selbst wenn Du wieder auf das
erste Package umschaltest, denn der lexical Scope ist
in dem Fall die ganze Datei.
>>Wenn Du Package-Globals fernab ihrer Deklaration zugreifst,
>>solltest Du sie immer mit dem Package-Präfix versehen, à la
>
> Das ist sicher eine Option, aber ich war bisher der Meinung, dass
> dies nicht notwendig sei.
Tja, man lernt in Perl eben nie aus :)
> Außerdem interessiert mich hier schlicht
> und einfach das "Warum" - ich bin nämlich der Ansicht, dass dies
> ein Bug ist, solange bis mich jemand eines Besseren belehrt.
Das "Warum" kann ich Dir nicht beantworten, dazu müsste man sich
anschauen, wie our genau realisiert ist. Ein Bug ist
es meiner Ansicht nach nicht, da es sich so verhält wie
dokumentiert. Dass ich dieses Verhalten wie Du für krautig halte,
steht auf einem anderen Blatt.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Frage zu Packages und our
"Ferry Bolhar" <bol [at] adv.magwien.gv.at> wrote:
> Frank Seitz:
>
>> Es verhält sich so, wie es definiert ist, siehe perldoc -f our:
>>
>> An "our" declaration declares a global variable that will be
>> visible across its entire lexical scope, even across package
>> boundaries. The package in which the variable is entered is
>> determined at the point of the declaration, not at the point of
>> use.
>
> Ich sehe da keinen Widerspruch - ich deklariere eine Variable
> im Package Alpha (daher kommt sie in das Package Alpha)
> und eine zweite im Package Beta (daher wird sie Teil des
> Packages Beta). Das sind doch zwei verschiedene Variable,
> daran besteht ja wohl kein Zeifel, oder?
Ich zweifle schon, denn da steht dass eine *globale* Variable definiert
wird, die über Paketgrenzen sichtbar ist. Wenn du die Pakete in
unterschiedliche Blöcke oder Dateien auslagerst (unterschiedlicher
lexical scope, dann werden es zwei verschiedene. Allerdings kannst du
dann nicht mehr so einfach darauf zugreifen.
Gruß, Frank
--
Arguing that cdbs is good because make is a least common denominator
language in Debian is like arguing that we should do GRs in iambic
pentameter because English is the lingua franca. :) vorlon
Re: Frage zu Packages und our
Ferry Bolhar schrieb:
> Hallo,
>
> ich bin auf ein (zumindest für mich :-) merkwürdiges Verhalten bei
> der Verwendung von Packages und "our" gestoßen, das ich mir
> nicht erklären kann.
>
Hi. Erweitere den Testcode doch etwas:
>
> use strict;
> use warnings;
> package Alpha;
> our $test =3D 10;
> print "Alpha: $test\n";
print "Alpha::test " . $Alpha::test ."\tBeta::test " . $Beta::test
.."\n";
> package Beta;
> our $test =3D 20;
> print "Beta: $test\n";
print "Alpha::test " . $Alpha::test ."\tBeta::test " . $Beta::test
.."\n";
> package Alpha;
> print "Alpha: $test\n";
print "Alpha::test " . $Alpha::test ."\tBeta::test " . $Beta::test
.."\n";
>
> liefert dieses Ergebnis:
>
> Alpha: 10
> Beta: 20
> Alpha 20
>
Ausgabe:
Alpha: 10 Alpha::test 10 Beta::test
Beta: 20 Alpha::test 10 Beta::test 20
Alpha: 20 Alpha::test 10 Beta::test 20
Alles klarer? (weiß nicht wieso es so ist, aber naja....
Re: Frage zu Packages und our
Frank Seitz:
> Das "Warum" kann ich Dir nicht beantworten, dazu müsste man sich
> anschauen, wie our genau realisiert ist.
Jetzt hast du mich darauf gebracht - manchmal sieht man den ganzen
Wald vor lauter Bäumen nicht. ;-)
Ich habe jetzt Folgendes festgestellt:
Wird das "strict" - Pragma (eigentlich das "strict vars") Pragma
verwendet, so erlaubt der Compiler die Verwendung von unqua-
lifizierten Namen nur, wenn diese als lexikalische Variable mit "my"
deklariert wurden. Geht ja auch nicht anders, da diese ja per
Default keinem Package angehören.
Mit der Einführung von "strict" kam das Bedürfnis, auch globale
Variable als solche deklarieren zu können, wozu "our" implementiert
wurde. Der Compiler selbst schaut jedoch bei einem unqualifizierten
Namen nach wie vor nur nach, ob es eine lexikalische Variable mit
diesem Namen gibt (dh., er schaut im Scratchpad des aktuellen
lexikalischen Bereiches nach, ob es dort eine solche Variable gibt).
Was macht "our" daher? Ganz einfach: es legt eine globale Variable
im jeweiligen Namensbereich an _UND_ definiert einen lexikalischen
Alias auf diese. Damit ist der Compiler zufrieden - ein Zugriff auf
den unqualifizierten Namen schaut für ihn aus wie der Zugirff auf eine
vorhandene lexikalische Variable, aber durch den Alias wird zur
Laufzeit tatsächlich auf die globale (Package) Variable zugegriffen.
Das erklärt auch die Scoping-Eigenschaften von "our", die denen
von "my" ident sind - denn ein innerhalb eines Scopes deklariertes
"our" wird außerhalb des Scopes wieder unwirksam, da der von
"our" angelegte lexikalische Alias - wie jede lexikalische Komponente -
beim Verlassen des Scopes verworfen wird.
Kein Problem, solange im selben Scope nicht:
- auch noch eine gleichnamige lexikalische Variable deklariert, oder
- in unterschiedlichen Packages dieselbe globale Variable mehrfach
deklariert wird.
Ganz krass zeigt sich dies bei folgendem Code, der auch mit "use
warnings" und "use strict" ohne jeden Protest durchgeführt wird:
my $test = 'lexical';
print "$test\n";
package Alpha;
our $test = 'Alpha:global';
print "$test\n";
package main;
print "$test\n";
ergibt:
lexical
Alpha:global
Alpha:global
dh., der Wert der lexikalischen Variable wird ganz einfach durch den von
"our" angelegten Alias überschrieben. Das "package main" nützt da nichts,
da in "main" ja keine $test Variable angelegt wurde (und auch dann würde
deren Alias durch den später in "Alpha" angelegten Alias überschrieben).
Und da kann man mir sagen, was man möchte - das ist sicher nie beabsichtigt,
daher sollte Perl - wie es das ja auch tut, wenn mit "my" oder "our" zweimal
irrtümlich dieselbe Variable in einem Scope deklariert werden soll - eine
entsprechende Warnungsmeldung ausgeben.
> Dass ich dieses Verhalten wie Du für krautig halte, steht auf einem
anderen Blatt.
Ja, IMHO wurden durch die Einführung von "our" und der jetzigen
Implementierung mehr Probleme geschaffen, als damit gelöst wurden. "use
vars" hat jahrelang vollkommen ausgereicht. Ein gutes Beispiel, dass man
es auch übertreiben kann, denn wozu soll die Deklaration einer _globalen_
Variable, die nur einen _lexikalischen_ Gültigkeitsbereich hat, gut sein?
Naja, warten wir ab, ob sich da in Perl 6 was ändern wird...
Schöne Grüße, Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol [at] adv.magwien.gv.at