Thread Variablen in Sub's - strict meckert rum. (20 answers)
Opened by popcorn5 at 2007-04-26 20:29

sid burn
 2007-04-28 02:59
#76302 #76302
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
[quote=PerlProfi,27.April.2007, 22:34]Danke für die ausführliche Erklärung mit der Symboltabelle.
Aber:
Quote
Solange also deine Variable lebt und da etwas auf den Code zeigt wird deine Subroutine nicht zerstört und auch nicht ewig neu Kompiliert.

Auser natürlich deine variable verlässt den Gültigkeitsbereich, und du rufst die Subroutine neu auf die dir dann wieder die Subroutine erstellt.

Da liegt ja gearde meine Frage, wenn ich folgenden code habe:
Code: (dl )
1
2
3
4
sub aussen
{
my $innen = sub { 1...10 };
} # aussen

Wird dann jedesmal wenn ich aussen() aufrufe die innere Subroutine - $innen - neu kompiliert ?
So wie ich das verstanden habe schon, aber wie kann ich denn jetzt Modularisieren ohne das mir das passiert ?

MfG[/quote]
Ja $innen wird immer neu zugewiesen. Allerdiengs in diesem beispiel nicht 100%ig alles neu Kompiliert. Was da jetzt genau abläuft weiß ich nicht genau. Aber in dem beispiel ist dein Code ja fest und es ändert sich nicht. Daher wird dein Code schon vorher Kompiliert, du hast nur ein Overhead weil du jedesmal den Code wieder einer Variablen zuweist.

Richtig Kompiliert würde nur dann, wenn du ein
Code: (dl )
eval "sub { 1 .. 10 }"
machst, denn dann wird der String erst wirklich zur Laufzeit Kompiliert und ausgewertet.

Das bei einen normalen sub ohne eval() schon etwas zur Laufzeit passiert kannst du auch daran sehen wenn du Syntaxfehler einbaust, den die werden schon vor dem Ausführen deines Skriptes abgefangen.


Ansonsten ist dein Beispiel ja ziemlich nutzloß. Deswegen kann ich nicht sagen wie du es jetzt Modulasieren solltest. Es hängt davon ab was du machen möchtest.

Möchtest du eine Sub einfach nur in einer Variable nutzen kannst du gleich das hier machen:
Code: (dl )
1
2
3
4
5
package test;
my $function = sub { 1 .. 10 };

# später...
$function->();


Ansonsten kannst du die Technik auch nutzen für Closures. Wenn du Klassenmethoden schreiben möchtest die dir z.B. ausgeben wieviele Klassen du erzeugt hast.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package test;
my $counter_incr;
my $counter_decr;
{
my $counter = 0;
$counter_incr = sub { $counter++ };
sub get_counter {
return $counter;
}
$counter_decr = sub { $counter-- };
}

sub new {
# Objekt erzeugen
$counter_incr->();
}

sub DESTROY {
$counter_decr->();
}


Damit hast du eine Closure und zwei Funktionen die nur in der Datei gültig sind. In der Datei sollte ja üblicherweise nur die Klasse sein.

Damit ist es nicht Möglich das jemand fremdes die Klassenmethoden von hand aufrufen kann, und den counter irgendwie Manipulieren kann.

Auch für das automatische erzeugen von get oder set Accessors kannst du das ganze nutzen.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package test;
use vars '$AUTOLOAD';

sub AUTOLOAD {
my $method = $AUTOLOAD;
$method =~ s/.*:://;

if ( my $attr = $method =~ m/^get(_.*)/ ) {
no strict 'refs';
*{__PACKAGE__ . "::get$attr"} = sub {
my ($self) = @_;
return $self->{$attr};
};
goto &$AUTOLOAD;
}
}


Wenn dein Object z.B. auf ein hash basiert und alle Keys z.B. folgendermaßen benannt sind:

_title
_subtitle
_text

etc. dann brauchst du jetzt z.B. keine get Methoden mehr schreiben. Wenn du ein Objekt nutzt und das erstemal die Funktionen aufrufst:

get_title()
get_subtitle()
get_text()

dann werden Sie erzeugt. bzw. Sie existieren ja noch nicht, und werden dann von AUTOLOAD erzeugt. Allerdiengs werden Sie nur beim ersten Aufruf erzeugt. Danach bei jedem weiteren Aufruf existieren die Methoden bereits, und müssen nicht mehr erneuert erzeugt werden.

Naja du musst sicherlich noch mehr machen für ein Korrektes Beispiel und keines der Beispiel soll oben vollständig sein, ich hoffe nur die Sachen die man damit machen kann sind erklärend genug.

Normalerweise müsstest du noch eine Liste bereit stellen welche Attribute du hast, damit nicht gleich für alles was mit "get_" anfängt auch gleich eine Methode erstellt wird, obwohl du gar nicht so ein Attribut anbietest.

Und DESTROY muss man entweder auch in AUTOLOAD abfangen, oder am besten zumindest eine DESTROY Methode erstellen die mindestens

"$self->SUPER::DESTROY()" aufruft.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de

View full thread Variablen in Sub's - strict meckert rum.