Global Variable in einem Block deklarieren
alligator
- perl
Hallo zusammen,
ist es möglich eine globale Variable erst in einem Block zu deklarieren ?
Hier mal ein Beispiel:
use strict;
use warnings;
my $var = "Fische";
print " Hallo $var \n";
{
our $var2 = "Hunde";
print " Hallo $var2 \n";
}
print " Hallo $var \n";
print " Hallo $var2 \n";
Das gibt folgende Fehlermeldung:
Variable "$var2" is not imported at D:\Proggen\Perl\our.pl line 15.
Wie kann ich denn die Variable $vars "importieren" ?
cya
alligator
Moin!
ist es möglich eine globale Variable erst in einem Block zu deklarieren ?
Hier mal ein Beispiel:use strict;
use warnings;my $var = "Fische";
print " Hallo $var \n";
{
our $var2 = "Hunde";
print " Hallo $var2 \n";
}
print " Hallo $var \n";
print " Hallo $var2 \n";Das gibt folgende Fehlermeldung:
Variable "$var2" is not imported at D:\Proggen\Perl\our.pl line 15.
Wie kann ich denn die Variable $vars "importieren" ?
"An our declares the listed variables to be valid globals within the enclosing block, file, or eval. That is, it has the same scoping rules as a "my" declaration, but does not create a local variable."
Das heisst, $var2 wird an der schliessenden geschweiften Klammer vergessen.
Du kannst aber ganz normal
use vars qw/$var2/;
schreiben, auch innerhalb des Blocks. Du solltest $var2 dann aber nicht weiter oben im Quelltext verwenden.
So long
Hi,
hmm was ist denn dann der Unterschied zwischen my und our ?
Ich dachte, das my "lokal" ist und our "global" ?!?
cya
alligator
Re!
hmm was ist denn dann der Unterschied zwischen my und our ?
Ich dachte, das my "lokal" ist und our "global" ?!?
Dazu koennte ich auch nur repetieren, was in 'perldoc -f our' steht. Wozu man das 'our' nun eigentlich braucht, ist an mir aber irgendwie vorbeigegangen. Ich benutze es daher auch nicht. Vielleicht weiss es ja jemand anderes.
So long
Halihallo Calocybe
hmm was ist denn dann der Unterschied zwischen my und our ?
Ich dachte, das my "lokal" ist und our "global" ?!?
Dazu koennte ich auch nur repetieren, was in 'perldoc -f our' steht. Wozu man das 'our' nun eigentlich braucht, ist an mir aber irgendwie vorbeigegangen. Ich benutze es daher auch nicht. Vielleicht weiss es ja jemand anderes.
Mit my deklarierte Variablen lassen sich von anderen Packages (eg. main::) nicht
ansprechen, da sie im Stack (der "lexikalische Scope") des Moduls gespeichert werden.
our ist nach der Dokumentation eine Art "Durchschnitt" zwischen globalen Variablen
(diese werden in der Symbol-Table des main:: Moduls referenziert) und den lokalen
Variablen die eben im aktuellen Scope definiert sind. Durchschnitt deshalb, da sie
So habe ich es zumindest verstanden (könnte mich also auch irren).
Viele Grüsse
Philipp
Halihallo nochmals
Mit my deklarierte Variablen lassen sich von anderen Packages (eg. main::) nicht
ansprechen, da sie im Stack (der "lexikalische Scope") des Moduls gespeichert werden.
our ist nach der Dokumentation eine Art "Durchschnitt" zwischen globalen Variablen
(diese werden in der Symbol-Table des main:: Moduls referenziert) und den lokalen
Variablen die eben im aktuellen Scope definiert sind. Durchschnitt deshalb, da sie
- und damit komme ich auf die eigentliche Antwort der Frage - eben trotz lokalem
Charakter (Modul-Stack) von anderen Modulen ausgelesen werden können.
Komisch...:
---
use strict;
print $test::test."\n";
while ( my ($n,$v) = each %{test::} ) {
print "$n=$v\n";
}
package test;
use strict;
my $test = '15';
BEGIN {$test = 'test';}
1;
---
die Variable $test ist im Modul test über my deklariert. Erwartungsgemäss wird die
Variable über main::print($test::test) nicht ausgegeben, aber etwas erstaunt mich:
Die Variable $test::test wird trotz lokaler Definition in der Symbol-Tabelle
referenziert. Das spricht gegen mein "Weltbild", da ich davon überzeugt war, dass
Variablen über 'my' im Stack (Perl ist stackorientiert, nicht zu verwechseln mit dem
Stack-Segment bei 3GL Languages) gespeichert werden und nicht in der Symbol-Tabelle
referenziert sind, da dort referenzierte Variablen IMHO eben den "Modul-Variablen" über
use vars qw/.../ entsprechen.? - Warum werden in der Symbol-Tabelle lokale Variablen
gespeichert? - Die sollte IMHO Modul-Charakter haben (also Modul-Variablen enthalten)...
Kann mir das jemand erklären?
Viele Grüsse
Philipp
Hallo,
leider kann ich dir nicht wirklich folgen.
Was ich an dem QT-Bespiel nicht verstehe ist, was in diesem
Hash %{test::} drin steht bzw. warum das drin steht, was er mir da ausgibt ?!?
cya
alligator
Halihallo alligator
leider kann ich dir nicht wirklich folgen.
Es geht etwas in die Internals von Perl. Etwas genauer geht es um die
interne Repräsentation von Variablen. Wie und wo diese gespeichert werden und ggf.
welche Konsequenzen damit hervorgerufen werden.
Was ich an dem QT-Bespiel nicht verstehe ist, was in diesem
Hash %{test::} drin steht bzw. warum das drin steht, was er mir da ausgibt ?!?
test war ja ein "test-Modul", dieses hat einen eigenen "Scope", d.h. Variablen, die
darin definiert sind, sind nicht "öffentlich", es sei denn man definiert sie mit
our oder use vars qw(...). Nun geht es mir um die Frage: Worin liegt genau der
Unterschied öffentlicher und privater Variablen. Perl verwaltet intern lokale
Variablen in einem Stack. Springt der Interpreter in eine neue Funktion, die zwei
Variablen $foo und $bar definiert, werden diese in den Modul-Stack gepushed; dort können
sie nach beliben geändert/undefiniert/wiederdefiniert werden, bis der Interpreter aus
der Funktion springt (eg. durch return), dann werden diese Variablen aus dem Stack
gepoped und so spricht man von "die Variable ging aus dem Scope". Etwas genauer gesagt,
wird der Referenzzähler um 1 verkleinert (das heisst, die Variable wird jetzt einmal
weniger gebraucht). Wurde die Variable nirgens sonst referenziert (eine Referenz darauf
gelegt), wird dieser Referenzzähler 0 und das Garbage Collection-System kann den
Speicherplatz der Variablen freigeben, da sie nicht mehr gebraucht wird.
OK, was hat das alles mit %{test::} zu tun? - %{test::} greift auf die sogenannte
"Symbol-Tabelle" des Moduls test zu. Die Symbol-Tabelle verwaltet (meiner bisherigen
Meinung nach: globale) Variablen (d.h. es ist eine Art Hash, der als Key den Namen
der Variablen speichert und der Value ist ein C-Pointer auf die Variablen-Datenstruktur).
Nun gut, da die Symbol-Tabelle nicht nur globale Variablen referenziert, wie ich bis
anhin dachte, nehme ich an, dass dies aufgrund der Performance gemacht wurde. Kommt eine
Variable in den aktuellen Scope wird sie in der Symbol-Tabelle referenziert, sodass
der Perlinterpreter schneller darauf zugreifen kann (man stelle sich vor, man müsste
bei jedem Zugriff durch den ganzen Stack nach der Variablen durchsuchen).
Hm, ist es das? - Die Performance?
OK, zurück zu dir alligator: ;)
Vereinfacht ausgedrückt, siehst du in %{main::} einfach alle aktiven Variablen, wenn
mich meine Feststellung nicht täuscht. Das * ist C-style und bedeutet "Referenz", du
hast also etwas wie:
test => *test::test
das heisst: "test" ist eine Variable, *test::test zeigt auf die interne Repräsentation
des Wertes dieser Variablen (sei sie nun Skalar, Hash, Array, Filehandle oder
eine sogenannte MagicVariable). OK, auf *test::test kannst du nicht zugreifen, das ist
einfach Text. Der Perlinterpreter hat dort aber wirklich eine Referenz auf die
Variable gesetzt, sodass er %{main::} einfach nach dem Variablen durchsuchen muss und
dann gleich die Referenz auf die Datenstruktur hat.
--- our vs use vars qw() vs my ---
Hm. our definiert eine Variable wie my, mit dem Unterschied, dass sie in der Symbol-
Tabelle sozusagen "global freigegeben wird" (wie das intern umschrieben wird, enzieht
sich leider meinem Wissen). my-Variablen werden wie ich jetzt festgestellt habe auch
in der Symbol-Table referenziert, aber man kann von ausserhalb des Moduls nicht darauf
zugreifen (entweder fremde Module können nicht auf den Modul-Stack zugreifen, oder intern
wird ein flag auf "restricted_to_module" gesetzt). Bei use vars qw(...) könnte ich mir
vorstellen, dass die Variablen nicht in den Stack gepushed werden, sondern als
"standalone" irgendwo im Speicher definiert sind und lediglich in der Symbol-Tabelle
referenziert sind, da sie so nie aus dem Scope geraten (vom Stack entfernt werden),
sind sie immer definiert und von überall her zugreifbar => global.
---
WARNUNG: Das sind einfach meine Gedanken dazu, ich habe keine verbindliche Basis
dafür.
Wer sich für die Internals interessiert:
perldoc perlguts
perldoc perlcall
perldoc perlapi
perldoc perlinternal
perldoc perlhack
...
ach, einfach perldoc perltoc!
OK, ich glaube ich sollte mich selber noch tiefer damit befassen :-)
Hoffe das war einigermassen verständlich, ist nämlich nicht einfach zu erklären :-)
Viele Grüsse
Philipp
Hi,
ohh damn.
Danke für die ausführliche Info. Auf jeden Fall ists mir jetzt etwas klarer. Ich kämpfe mich nämlich grad durch "Programmieren mit Perl" und ich verstehe bzw. sehe den Sinn teilweise in manchen Abschnitten einfach nicht, obwohl ichs x-mal durchlese. Aber der Teil mit
--- our vs use vars qw() vs my --- hat mir auf jeden Fall weiter geholfen.
cya
alligator
Halihallo alligator
Danke für die ausführliche Info. Auf jeden Fall ists mir jetzt etwas klarer. Ich kämpfe mich nämlich grad durch "Programmieren mit Perl" und ich verstehe bzw. sehe den Sinn teilweise in manchen Abschnitten einfach nicht, obwohl ichs x-mal durchlese.
Nur fragen; wie es scheint beliebt es mir über die Internals zu sprchen :-)
Aber der Teil mit
--- our vs use vars qw() vs my --- hat mir auf jeden Fall weiter geholfen.
Darf ich nochmals kurz darauf hinweisen, dass das wirklich nur im Optimalfall der
Wahrheit entspricht. Es sind meine Gedanken dazu, nicht mehr und nicht weniger.
Eine fundierte Grundlage habe ich dazu nicht, ich rate nur wie der Perlinterpreter
funktioniert und hoffe darauf, dass es mit der Wahrheit konform ist.
Viele Grüsse
Philipp
Hook,
also ich hab jetzt nochmal in einem Büchle von O´Reilly (Perl 5.6 kurz & gut)nachgeschaut und da steht drin, dass
use vars "NAMEN"veraltet sei und man statt dessen our
verwenden soll. Also schliesse ich daraus, dass use vars und our identisch bei der Funktion sind, bis auf das halt our neuer ist.
Naja für mein Ursprungsproblem bringt mich das nicht weiter ...
cya
alligator
Hi,
use vars "NAMEN"veraltet sei und man statt dessen our
verwenden soll. Also schliesse ich daraus, dass use vars und our identisch bei der Funktion sind, bis auf das halt our neuer ist.
Das ist es sicher nicht. Die Zeit der auswirkung ist nämlich eine ganz andere. Da "use vars" über use eingebunden wird, wird es schon zur kompilierzeit eingebunden, our, oder ähnliche Konstrukte können erst zu Laufzeit evaluiert werden.
Daher dürfte es auch egal sein, wo use vars steht (solange es im gleichen Namensraum ist). Selbst wenn es am Ende des Scriptes steht, wirkt es sich auch schon auf den Anfang aus.
Grüße Andres Freund
Moin!
Mit my deklarierte Variablen lassen sich von anderen Packages (eg. main::) nicht
ansprechen, da sie im Stack (der "lexikalische Scope") des Moduls gespeichert werden.
our ist nach der Dokumentation eine Art "Durchschnitt" zwischen globalen Variablen
(diese werden in der Symbol-Table des main:: Moduls referenziert) und den lokalen
Variablen die eben im aktuellen Scope definiert sind. Durchschnitt deshalb, da sie
- und damit komme ich auf die eigentliche Antwort der Frage - eben trotz lokalem
Charakter (Modul-Stack) von anderen Modulen ausgelesen werden können.
Naja, das stimmt nicht ganz. Die our-Variable wird im Symbol-Table des packages gespeichert, in dem sie deklariert wird, nicht unbedingt main::.
Im Prinzip ist 'our' nur ein Shortcut, um von einem anderen package aus, das sich aber im selben lexikalischen Scope befindet (i.e. mehrere Module in derselben Datei), ohne volle Qualifizierung (also volle $package::var-Angabe) auf die Variable zuzugreifen.
Schoen und gut, aber die entscheidende Frage ist doch, welchen Sinn hat das? Mir scheint, das hilft nur in eingen Faellen, mit einem schlechten Design doch noch irgendwie zurecht zu kommen.
use strict;
print $test::test."\n";
while ( my ($n,$v) = each %{test::} ) {
print "$n=$v\n";
}package test;
use strict;
my $test = '15';
BEGIN {$test = 'test';}1;
die Variable $test ist im Modul test über my deklariert. Erwartungsgemäss wird die
Variable über main::print($test::test) nicht ausgegeben,
Jedenfalls nicht das $test, das Du mit my deklarierst.
aber etwas erstaunt mich: Die Variable $test::test wird trotz lokaler Definition in der Symbol-Tabelle referenziert.
Referenziert? Meinst Du, dass ihre Existenz in der Schleife angezeigt wird? Das duerfte daran liegen, dass Du sie vorher mit dem print-Kommando auto-vivified hast.
Das spricht gegen mein "Weltbild", da ich davon überzeugt war, dass
Variablen über 'my' im Stack (Perl ist stackorientiert, nicht zu verwechseln mit dem
Stack-Segment bei 3GL Languages) gespeichert werden und nicht in der Symbol-Tabelle
referenziert sind, da dort referenzierte Variablen IMHO eben den "Modul-Variablen" über
use vars qw/.../ entsprechen.? - Warum werden in der Symbol-Tabelle lokale Variablen
gespeichert? - Die sollte IMHO Modul-Charakter haben (also Modul-Variablen enthalten)...
Nun ja, es gibt hier zwei $test's im package test::. Eine Modul-Variable, die nur existiert, weil Du mit print darauf zugegriffen hast (Auto-Vivification), und dann die my-Variable, die aufgrund ihrer Position auch im ganzen package test:: sichtbar ist, aber nicht von aussen (main::). Das einzige, was mich wundert, ist dass im BEGIN auf die my-Variable zugegriffen wird, nicht auf die Modul-Variable. Man sieht das, wenn man den BEGIN-Block zu
BEGIN {$test::test = 'test';}
abaendert. Dann wird im print-Statement 'test' ausgegeben, da die Variable dann schon eher exisitert und nicht mehr auto-vivified wird. Aber muesste das BEGIN nicht eher als das my-Statement ausgefuehrt werden und daher auf die Modul-Variable $test::test zugreifen (und dabei abgebrochen werden, weil es gegen use strict verstoesst)?
So long
Halihallo Roland
Mit my deklarierte Variablen lassen sich von anderen Packages (eg. main::) nicht
ansprechen, da sie im Stack (der "lexikalische Scope") des Moduls gespeichert werden.
our ist nach der Dokumentation eine Art "Durchschnitt" zwischen globalen Variablen
(diese werden in der Symbol-Table des main:: Moduls referenziert) und den lokalen
Variablen die eben im aktuellen Scope definiert sind. Durchschnitt deshalb, da sie
- und damit komme ich auf die eigentliche Antwort der Frage - eben trotz lokalem
Charakter (Modul-Stack) von anderen Modulen ausgelesen werden können.Naja, das stimmt nicht ganz. Die our-Variable wird im Symbol-Table des packages gespeichert, in dem sie deklariert wird, nicht unbedingt main::.
Richtig, da habe ich mich kreuz falsch ausgedrückt.
Schoen und gut, aber die entscheidende Frage ist doch, welchen Sinn hat das? Mir scheint, das hilft nur in eingen Faellen, mit einem schlechten Design doch noch irgendwie zurecht zu kommen.
Mit deiner Definition scheint mir das auch so. Das einzige Gegenargument ist für mich,
dass man über use vars und our die Variablen als "Modulvariablen" (meinetwegen im
ganzen lexikalischen Scope) definiert und diese nicht über Konstrukte wie $test::test='1'
iniziieren muss.
die Variable $test ist im Modul test über my deklariert. Erwartungsgemäss wird die
Variable über main::print($test::test) nicht ausgegeben,
Jedenfalls nicht das $test, das Du mit my deklarierst.
Ja, der Default SV_undef.
aber etwas erstaunt mich: Die Variable $test::test wird trotz lokaler Definition in der Symbol-Tabelle referenziert.
Referenziert? Meinst Du, dass ihre Existenz in der Schleife angezeigt wird? Das duerfte daran liegen, dass Du sie vorher mit dem print-Kommando auto-vivified hast.
Schande über mich, das isses! - *JIARGL*, danke.
Nun ja, es gibt hier zwei $test's im package test::. Eine Modul-Variable, die nur existiert, weil Du mit print darauf zugegriffen hast (Auto-Vivification), und dann die my-Variable, die aufgrund ihrer Position auch im ganzen package test:: sichtbar ist, aber nicht von aussen (main::). Das einzige, was mich wundert, ist dass im BEGIN auf die my-Variable zugegriffen wird, nicht auf die Modul-Variable. Man sieht das, wenn man den BEGIN-Block zu
Das die lokale Variablen eine hörere "Priorität" haben ist eigentlich logisch. Perl
greift zuerst auf den Stack zu, falls dort keine Variable gefunden wird, ist die
Symbol-Tabelle (also jetzt doch die Referenzierung aller "Modulvariablen") ein
Fall-Back.
Beispiel:
package test;
our $test = 15;
sub test {
my $test = 27;
print $test;
}
Was sollte ausgegeben werden? - Natürlich 27, Zugriff auf die lokale Variable test.
BEGIN {$test::test = 'test';}
abaendert. Dann wird im print-Statement 'test' ausgegeben, da die Variable dann schon eher exisitert und nicht mehr auto-vivified wird. Aber muesste das BEGIN nicht eher als das my-Statement ausgefuehrt werden und daher auf die Modul-Variable $test::test zugreifen (und dabei abgebrochen werden, weil es gegen use strict verstoesst)?
Nicht umbedingt. BEGIN wird zwar zuerst _ausgeführt_, nicht aber zuerst geparsed und
optimized. Ich begebe mich jetzt wieder auf argumentatives Dünneis:
use strict;
my $test = 15;
sub t {
print $test;
}
t();
1;
funktioniert, aber:
use strict;
sub t {
print $test;
}
my $test = 15;
t();
1;
aha, $test nicht definiert. Warum? - Als der Parser $test in t() sieht, existierte
die Variable noch nicht auf dem Stack und war auch nicht lokal definiert. Was, wenn
nicht nur auf die Existenz (vorherige Definition) der Variablen geprüft wird, sondern
diese auch gleich auf dem Stack angelegt wird? - Das würde das "Phenomen", dass bei
BEGIN {$test=15;} auf die vorherig definierte 'my'-Variable zugegriffen wird erklären,
denn diese wird lekikalisch zuerst definiert (auch wenn im Sinne von "Laufzeit" die
Variable erst nachher iniziiert wird).
Viele Grüsse
Philipp
Halihallo nochmals
Das die lokale Variablen eine hörere "Priorität" haben ist eigentlich logisch. Perl
greift zuerst auf den Stack zu, falls dort keine Variable gefunden wird, ist die
Symbol-Tabelle (also jetzt doch die Referenzierung aller "Modulvariablen") ein
Fall-Back.
Das war nur der Vollständigkeits-halber, das dürfte ja jedem Bekannt sein.
BEGIN {$test::test = 'test';}
abaendert. Dann wird im print-Statement 'test' ausgegeben, da die Variable dann schon eher exisitert und nicht mehr auto-vivified wird. Aber muesste das BEGIN nicht eher als das my-Statement ausgefuehrt werden und daher auf die Modul-Variable $test::test zugreifen (und dabei abgebrochen werden, weil es gegen use strict verstoesst)?
zweiter Versuch:
Die Definition und die Iniziierung sind zwei Prozesse. Erstere geschieht zur
Compiletime (und zwar _vor_ dem Ausführen von BEGIN, dieses schliesst die Compilier-
Phase einfach ab), letzteres zur Laufzeit (das gilt zwar auch bei lokalen Variablen
innerhalb von Prozeduren, jedoch werden dort die Variablen nicht erstellt, da deren
Existenz vom Aufruf der Prozedur abhängig sind). Wird eine lokale Variable (im Modul-
Scope; also nicht blockscoped) definiert, wird diese zur Compiletime mit undef
definiert. Bei my $test=5; ist $test zur Compiletime undef (und könnte somit in BEGIN
geändert werden), zur Laufzeit nach der Definition '5'.
Beispiel:
use strict;
my $test = 5;
print "$test";
BEGIN {
$test = 7;
print "$test,";
}
1;
gibt "7,5" aus. Da $test vor BEGIN deklariert wird, greift $test=7 in BEGIN auf die
zur Compiletime definierte (aber nicht iniziierte) Variable zu, setzt diese auf 7 und
gibt somit 7 aus. Nach BEGIN wird dieselbe Variable $test zur Laufzeit auf 5 gesetzt und
somit wird anschliessend 5 ausgegeben.
Das ist zumindest meine Erklärung für dieses "Phenomen".
Viele Grüsse
Philipp
Re!
Die Definition und die Iniziierung sind zwei Prozesse. Erstere geschieht zur
Compiletime (und zwar _vor_ dem Ausführen von BEGIN, dieses schliesst die Compilier-
Phase einfach ab), letzteres zur Laufzeit [...]
Ja, so sieht es wohl aus.
Ich muss sagen, mir ist der ganze Startup-Prozess von Perl sehr raetselhaft. Wahrscheinlich muss ich eines Tages doch mal den Perl-Source lesen, um zu kapieren, was da wirklich abgeht.
So long