# cat ./test.pl
#!/usr/bin/perl
use strict;
use warnings;
use lib "./";
our $myVarA = 1;
our $myVarB = 2;
use myTest;
print "\$myVarA = $main::myVarA\n";
print "\$myVarB = $main::myVarB\n";
# cat ./myTest.pm
package myTest;
print "\$myVarA = " . $main::myVarA . "\n";
print "\$myVarB = " . $main::myVarB . "\n";
1;
# perl ./test.pl
$myVarA =
$myVarB =
$myVarA = 1
$myVarB = 2
#
Soweit ich "use" verstanden habe, war das zu erwarten, da "use" vor dem
Kompilieren stattfindet. L�sen liese sich das "Problem", indem man
"use" durch "require" ersetzt.
Nun lese ich aber �berall, dass man "use" einem "require" wo immer
m�glich vorziehen soll. Ist obiges so eine Ausnahme, oder gibt es auch
einen "use"-Weg?
Ziel ist es, in einem package sicher zu stellen, dass bestimmte $main::
Variablen gesetzt wurden.
Danke und Gru�, Helmut
--
No Swen today, my love has gone away
My mailbox stands for lorn, a symbol of the dawn
#!/usr/bin/perl
use strict;
use warnings;
use lib "./";
BEGIN{
> BEGIN{
> our $myVarA = 1;
> our $myVarB = 2;
> }
Ah, bei BEGIN war ich sogar schon, aber vermutlich stimmte die
Reihenfolge nicht.
Merci, Helmut
Daran, dass es hakelig ist, l�sst sich ablesen, dass du ein
untaugliches Konzept verfolgst. Wenn du die Variablenwerte
$myVarA und $myVarB in myTest brauchst, �bergib sie
lieber als Parameter.
Gr��e
Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen f�r Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Homepage: http://www.fseitz.de/
XING-Profil: http://www.xing.com/profile/Frank_Seitz2
> Helmut Schneider wrote:
> >
> > Ziel ist es, in einem package sicher zu stellen, dass bestimmte
> > $main:: Variablen gesetzt wurden.
>
> Daran, dass es hakelig ist, l�sst sich ablesen, dass du ein
> untaugliches Konzept verfolgst. Wenn du die Variablenwerte
> $myVarA und $myVarB in myTest brauchst, �bergib sie
> lieber als Parameter.
package myLdap;
sub connectToLdap ($$$$$) {
my $_ldapDomain = shift;
my $_DC = shift;
my $_port = shift;
my $_ldapBindUser = shift;
my $_ldapBindPass = shift;
[...]
}
Jetzt will ich ein zuf�lliges Passwort erstellen und ben�tige hierf�r:
@alphanumeric = ('a'..'z', 'A'..'Z', 0..9, '!', '?', '$', '/', '.',
'.', '-', '+', '=');
$pwLength = 10;
Ausserdem soll Net::LDAP $retries mal versuchen, sich mit dem Server zu
connecten:
$retries = 5;
Von den obigen 3 Werten sind aus meiner Sicht mindestens eine konstant
(@alphanumeric), die m�ssen nicht unbedingt jedesmal einer Subroutine
�bergeben werden. Das kostet doch auch Ressourcen, oder nicht (Objekt
�bergeben, Kopie erstellen, Kopie wieder l�schen)?!
In dem Fall kannst du da auch default Werte in die Funktion (oder Modul)
einbauen, aber dazu musst du doch keine Variabeln global zug�nglich machen.
Und was die Performance angeht.
Wenn du diese Funktion millionenmal in dem Skript aufrufst, dann k�nnte
es u.U. eine Rolle spielen. Wobei aber globale Variabeln in der Regel
eher performancekiller sind.
D.h. du solltest nat�rlich auch pr�fen, ob die von dir gew�nschte
vorgehensweise wirklich eine Verbesserung bringt (z.b. mit dem Modul
Benchmark).
Struppi.
Ich dachte mir, es macht die Sache vielleicht �bersichtlicher, wenn ich
das in main definiere.
> Und was die Performance angeht.
>
> Wenn du diese Funktion millionenmal in dem Skript aufrufst,
Unwahrscheinlich. :)
Es ist definitiv eine Ausnahme, dass Du in einem Modul, das mit use
eingebunden wird, Code hast, der sofort ausgef�ソスhrt wird und nicht nur
der Initialisierung dient. Normalerweise werden in Modulen nur
Funktionen bzw. Methoden definiert und eventuell ein paar Variablen
initialisiert. Wenn Du Dein myTest.pm so umschreibst:
package myTest;
sub print_vars {
print "\$myVarA = " . $main::myVarA . "\n";
print "\$myVarB = " . $main::myVarB . "\n";
}
1;
und dann in test.pl
myTest::print_vars()
aufrufst, wird es wie gew�ソスnscht funktionieren, weil der Aufruf zu einem
Zeitpunkt erfolgt, zu dem $main::myVarA und $main::myVarB schon
initialisiert sind.
Wenn $myVarA und $myVarB der Initialisierung von myTest dienen, dann
ist es vermutlich besser und lesbarer, Du �ソスbergibst sie gleich beim use:
use myTest (1, 2);
oder
use myTest (myVarA => 1, myVarB => 2);
und verwendest eine import-Routine in myTest.pm und dort package-globale
Variablen zu setzen.
Oder Du verwendest gleich den objektorientierten Ansatz:
use myTest;
$mytest = myTest->new(myVarA => 1, myVarB => 2);
dann kann die Methode new von myTest damit machen, was sie will (z.B. in
$mytest speichern, oder als package-globale Daten speichern oder
irgendwas damit berechnen und dann vergessen).
Ich tendiere meistens zu letzterem Ansatz.
hp
In der Funktion connectToLdap()? Wieso soll die ein zuf�lliges Passwort
erstellen?
> Ausserdem soll Net::LDAP $retries mal versuchen, sich mit dem Server zu
> connecten:
>
> $retries = 5;
Die Variable w�rde ich aber auf keinen Fall $main::retries nennen, da
sie spezifisch f�r Dein myLdap Modul ist. Wenn schon, dann hei�t sie
$myLdap::retries. Dann kannst Du sie in myLdap mit
our $retries = 5;
definieren und initialisieren und wenn n�tig im main mit
$myLdap::retries = 10;
�berschreiben.
Aber das schreit wirklich nach einem anderen Interface:
package myLdap;
sub connect {
my %opt = @_;
croak "no domain" unless $opt{domain};
$opt{port} //= 389;
$opt{retries} //= 5;
$opt{pwLength} //= 10;
...
}
und dann rufst Du
myLdap::connect(domain => 'example.net', user => 'joe', ...);
auf.
Oder Du machst Dir gleich ein myLdap Objekt. Die Wahrscheinlichkeit,
dass Du mal zwei davon brauchen k�nntest, ist ja nicht so klein ...
hp
Wenn dir die �bergabe zweier skalarer Parameter �ber den Stack
an eine Subroutine Kopfzerbrechen bereitet, weil dies zu viel Aufwand
sein k�nnte, solltest du lieber in Assembler programmieren.
Untaugliche Konzepte sind oft das Resultat fehlgeleiteter �berlegungen.
So auch hier. Das h�rt sich vielleicht arrogant an, ist auf
den Punkt gebracht aber der eigentliche Kern des Problems.
Gr��e
Frank Seitz
> $opt{port} //= 389;
Was bewirkt "//="?
> Oder Du machst Dir gleich ein myLdap Objekt. Die Wahrscheinlichkeit,
> dass Du mal zwei davon brauchen k�nntest, ist ja nicht so klein ...
Macht vermutlich Sinn, ja.
> Peter J. Holzer wrote:
> > $opt{port} //= 389;
> Was bewirkt "//="?
Leider sagt [1] darüber nichts. Wie auch += wird es wohl bedeuten:
$opt{port} = $opt{port} // 389;
Wobei // der Defined-Or Operator ist [2] und in diesem Fall den Hash
default-bedatet, wenn er nicht bereits per Übergabe bedatet wurde.
[1] http://perldoc.perl.org/perlop.html
[2] http://perldoc.perl.org/perlop.html#C-style-Logical-Defined-Or
Gruß,
Paolo
> Es ist definitiv eine Ausnahme, dass Du in einem Modul, das mit use
> eingebunden wird, Code hast, der sofort ausgeführt wird und nicht nur
> der Initialisierung dient. Normalerweise werden in Modulen nur
> Funktionen bzw. Methoden definiert und eventuell ein paar Variablen
> initialisiert. Wenn Du Dein myTest.pm so umschreibst:
>
> package myTest;
>
> sub print_vars {
> print "\$myVarA = " . $main::myVarA . "\n";
> print "\$myVarB = " . $main::myVarB . "\n";
> }
>
> 1;
>
> und dann in test.pl
>
> myTest::print_vars()
>
> aufrufst, wird es wie gewünscht funktionieren, weil der Aufruf zu einem
> Zeitpunkt erfolgt, zu dem $main::myVarA und $main::myVarB schon
> initialisiert sind.
Vielen Dank, jetzt verstehe ich, warum dieser Ansatz hier schon lange
funktioniert.
Welcher Ansatz wäre zu wählen, wenn test.pl ein Daemon ist (RPC-Server)
und selbst myTest.pm verwendet? Das Package benötigt verschiedene Daten
bei jedem Funktionsaufruf, die es ausliest oder auch ändert. Diese Daten
halte ich wie hier im "Daemon" test.pl und verwende sie im Package über
Namespace $main::. Ist für diesen Fall der Ansatz vertretbar oder doch
lieber der folgende:
> Wenn $myVarA und $myVarB der Initialisierung von myTest dienen, dann
> ist es vermutlich besser und lesbarer, Du übergibst sie gleich beim use:
>
> use myTest (1, 2);
> oder
> use myTest (myVarA => 1, myVarB => 2);
>
> und verwendest eine import-Routine in myTest.pm und dort package-globale
> Variablen zu setzen.
Wo kann ich dazu mehr lesen? In http://perldoc.perl.org/perlmod.html
habe ich soetwas nicht gefunden.
Gruß,
Paolo
> Was bewirkt "//="?
Neuer Operator in Perl 5.10. Aus perldelta:
> Defined-or operator
>
> A new operator "//" (defined-or) has been implemented. The following
> expression:
>
> $a // $b
>
> is merely equivalent to
>
> defined $a ? $a : $b
>
> and the statement
>
> $c //= $d;
>
> can now be used instead of
>
> $c = $d unless defined $c;
>
> The "//" operator has the same precedence and associativity as "||".
> Special care has been taken to ensure that this operator Do What You
> Mean while not breaking old code, but some edge cases involving the
> empty regular expression may now parse differently. See perlop for
> details.
LG, Ferry
--
Ing. Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolh...@wien.gv.at
> "Helmut Schneider":
>
> > Was bewirkt "//="?
>
> Neuer Operator in Perl 5.10. Aus perldelta:
>
> > Defined-or operator
> >
> > A new operator "//" (defined-or) has been implemented. The
> > following expression:
> >
> > $a // $b
> >
> > is merely equivalent to
> >
> > defined $a ? $a : $b
> >
> > and the statement
> >
> > $c //= $d;
> >
> > can now be used instead of
> >
> > $c = $d unless defined $c;
Praktisch. "unless" sollte ich mir auch angew�hnen.
Merci, Helmut
>>> $c = $d unless defined $c;
>
> Praktisch. "unless" sollte ich mir auch angew�hnen.
Nachgestellte Bedingungen sind in den Augen mancher Puristen aber
schlechter Programmierstil.
Helmut Wollmersdorfer
Hurra, noch ein Minenfeld. ;) Aber die "Gefahr" ist hier nicht gegeben,
ich hab die Bedingung so oder so gerne vorne stehen zwecks der
�bersichtlichkeit. "unless" l�sst beim �berfliegen besser zwischen "if"
und "if not" unterscheiden.
Aber Danke f�r die Warnung. :)
Perl ist in den Augen mancher Puristen schlechter Programmierstil.
SCNR,
hp
Warum sollte das einen Unterschied machen?
> Das Package ben锟絫igt verschiedene Daten bei jedem Funktionsaufruf, die
> es ausliest oder auch 锟絥dert. Diese Daten halte ich wie hier im
> "Daemon" test.pl und verwende sie im Package 锟絙er Namespace $main::.
Warum h锟絣tst Du sie im Namespace main::, wenn sie das Package ben锟絫igt?
Es ist doch viel einfacher und lesbarer, sie im Namespace des Packages
zu halten.
> Ist f锟絩 diesen Fall der Ansatz vertretbar oder doch
> lieber der folgende:
>
>> Wenn $myVarA und $myVarB der Initialisierung von myTest dienen, dann
>> ist es vermutlich besser und lesbarer, Du 锟絙ergibst sie gleich beim use:
>>
>> use myTest (1, 2);
>> oder
>> use myTest (myVarA => 1, myVarB => 2);
>>
>> und verwendest eine import-Routine in myTest.pm und dort package-globale
>> Variablen zu setzen.
>
> Wo kann ich dazu mehr lesen? In http://perldoc.perl.org/perlmod.html
> habe ich soetwas nicht gefunden.
Dort steht nur lapidar, dass (und wie) use die import-Routine des Moduls
aufruft. Was man dann damit anfangen kann, ist offenbar der Fantasie des
Lesers 锟絙erlassen. Hier ein kleines Beispiel:
package MyTest;
my $var1 = 23;
my $var2 = 17;
sub import {
my ($package, %options) = @_;
if (defined $options{param1}) {
$var1 = $options{param1};
}
if (defined $options{param2}) {
$var2 = $options{param2};
}
}
sub printvars {
print "var1 = $var1; var2 = $var2\n";
}
1;
__END__
#!/usr/bin/perl
use warnings;
use strict;
use MyTest;
MyTest->printvars();
__END__
#!/usr/bin/perl
use warnings;
use strict;
use MyTest param1 => 'foo', param2 => 4711;
MyTest->printvars();
__END__
Hier habe die Variablen $var1 und $var2 sogar lexikalisch definiert,
d.h., sie sind au锟絜rhalb ihres Scopes gar nicht erreichbar, man kann
also nicht mit $MyTest::var1 darauf zugreifen. Sollte auch nicht
notwendig sein.
hp
> > Das Package benötigt verschiedene Daten bei jedem Funktionsaufruf, die
> > es ausliest oder auch ändert. Diese Daten halte ich wie hier im
> > "Daemon" test.pl und verwende sie im Package über Namespace $main::.
> Warum hältst Du sie im Namespace main::, wenn sie das Package benötigt?
> Es ist doch viel einfacher und lesbarer, sie im Namespace des Packages
> zu halten.
Irgendwie war ich fälschlicherweise der Meinung, die Objekte des
Packages würden nach dem Funktionsaufruf nicht mehr existieren. Ich
verstehe nun, dass das Package nur einen Namensraum beschreibt, der
Definitionen bereithält etc. Code am Anfang wird sogar ausgeführt, nur
wie beim OP leider in der falschen Reihenfolge.
> Dort steht nur lapidar, dass (und wie) use die import-Routine des Moduls
> aufruft. Was man dann damit anfangen kann, ist offenbar der Fantasie des
> Lesers überlassen. Hier ein kleines Beispiel:
> ...
d.h. import() wird durch das use immer implizit aufgerufen? Diese
existiert aber nur, wenn explizit definiert oder geerbt?
Verstehe ich richtig, dass Exporter [1] genau den entgegengesetzten Weg
beschreibt? Wo gibt es denn hierfür sinnvolle Verwendung, wenn entweder
eine Variable nach main:: gehört oder aber besser zum Package, aber
nicht im Package definiert und trotzdem außerhalb verwendet wird.
Man würde sich auch nur das Tippen des Namensraums sparen, wenn bei
nicht lexikalisch (my) definierten Variablen immer auch über Package::
zugegriffen werden kann?
Gruß,
Paolo
Ob das die falsche oder richtige Reihenfolge ist, h�ngt nat�rlich von
der Intention ab. Sie werden unmittelbar nachdem das Modul kompiliert
wurde, ausgef�hrt, was ich zumindest f�r unmittelbar einsichtig halte
(wann sollte das sonst passieren?).
>> Dort steht nur lapidar, dass (und wie) use die import-Routine des Moduls
>> aufruft. Was man dann damit anfangen kann, ist offenbar der Fantasie des
>> Lesers �berlassen. Hier ein kleines Beispiel:
>> ...
>
> d.h. import() wird durch das use immer implizit aufgerufen? Diese
> existiert aber nur, wenn explizit definiert oder geerbt?
Ja.
> Verstehe ich richtig, dass Exporter [1] genau den entgegengesetzten Weg
> beschreibt?
Jein. Der Aufruf der von Exporter zur Verf�gung gestellten
import-Routine erfolgt genau gleich. Die tut dann nur was anderes als
die, die ich skizziert habe. W�hrend meine ihre Parameter als
Key/Value-Paare interpretiert und damit lokale Variablen initialisiert,
interpretiert Exporter::import ihre Variablen als Namen lokaler
Variablen bzw. Subroutinen, die es exportieren, d.h., im aufrufenden
Namensraum (das muss nicht main sein!) installieren soll.
Wenn also in package A ein
use B '$var', 'func';
vorkommt und B von Exporter erbt, dann ist nach diesem Statement
$A::var ein Alias von $B::var und &A::func ein Alias von &B::func.
> Wo gibt es denn hierf�r sinnvolle Verwendung, wenn entweder
> eine Variable nach main:: geh�rt oder aber besser zum Package, aber
> nicht im Package definiert und trotzdem au�erhalb verwendet wird.
> Man w�rde sich auch nur das Tippen des Namensraums sparen, wenn bei
> nicht lexikalisch (my) definierten Variablen immer auch �ber Package::
> zugegriffen werden kann?
Im wesentlichen ja. Aber Tipparbeit ersparen ist schon eine sinnvolle
Verwendung. Ein Programm wird nicht unbedingt lesbarer, wenn man dauernd
Math::Trig::sin() statt sin() tippen muss (ok, schlechtes Beispiel, weil
sin() eh builtin ist, aber ich glaube, es illustriert das Argument).
hp
>> d.h. import() wird durch das use immer implizit aufgerufen? Diese
>> existiert aber nur, wenn explizit definiert oder geerbt?
>
> Ja.
Sicher? Wurde das mal ge�ndert? Zumindest in einer fr�heren 5.8. Release,
bei der ich das mal getestet habe, wurde import() nur aufgerufen, wenn es
in der betreffenden Klasse vorhanden war, es wurde aber nicht vererbt.
Jetzt machst Du mich unsicher ;-). Aber ja, ich bin mir sicher. Sonst
k锟絥nte der Exporter n锟絤lich nicht funktionieren: Das Package das etwas
exportieren m锟絚hte, definiert ja selbst keine import-Routine sondern
erbt sie nur vom Exporter.
> Zumindest in einer fr锟絟eren 5.8. Release,
> bei der ich das mal getestet habe, wurde import() nur aufgerufen, wenn es
> in der betreffenden Klasse vorhanden war, es wurde aber nicht vererbt.
Kann ich mir nicht vorstellen, da h锟絫te mindestens halb CPAN nicht mehr
funktioniert.
Kleiner Test:
109% /usr/bin/perl -v
This is perl, version 5.005_03 built for i386-linux
Copyright 1987-1999, Larry Wall
...
110% cat Parent.pm
package Parent;
sub import {
print __PACKAGE__, "::import called:\n";
print "\t$_\n" for (@_);
}
1;
111% cat Child.pm
package Child;
use Parent;
@ISA = qw(Parent);
1;
112% cat test_import
#!/usr/bin/perl
use strict;
use Child qw(foo bar baz);
print "hallo\n";
113% ./test_import
Parent::import called:
Parent
Parent::import called:
Child
foo
bar
baz
hallo
锟絣tere Version von perl habe ich keine mehr ...
hp