Probleme mit AUTOLOAD in UNIVERSAL?

Probleme mit AUTOLOAD in UNIVERSAL?

am 06.11.2007 21:29:46 von Frank Seitz

Hallo zusammen,

um in Programmen nicht immer Kaskaden von uses schreiben
zu müssen, habe ich eine AUTOLOAD-Methode geschrieben,
die ich in UNIVERSAL installiere, die beim ersten
Methodenaufruf für eine Klasse das betreffende Modul
automatisch lädt und dann die Methode aufruft. Code:

package UNIVERSAL;

sub AUTOLOAD {
my $this = shift;

my ($module,$sub) = our $AUTOLOAD =~ /^(.*)::(\w+)$/;
return if $sub !~ /[^A-Z]/;

eval "use $module";
die $@ if $@;

return $this->$sub(@_);
}

Scheint zu funktionieren.

Es gibt auf CPAN Module, die dasselbe oder ähnliches tun.
Ich habe mir diese nicht genauer angesehen, sie scheinen
komplizierter zu sein. In einer Doku habe ich einen Kommentar
gefunden, der mich nachdenklich macht:

There are many other issues with AUTOLOAD that this module
does not address. Primary among them is the fact that if
you call a function that does not exist in a package that
inherits from one with an AUTOLOAD, Perl will do a method search
for that AUTOLOAD. This is why this module does not install
AUTOLOAD in UNIVERSAL by default, and it is strongly
suggested that you not do so either.
(http://search.cpan.org/~tilly/Class-AutoloadCAN-0.03/lib/Cl ass/AutoloadCAN.pm)

Hat jemand eine Idee, was das angesprochene Problem
mit AUTOLOAD in UNIVERSAL sein soll? Ich verstehe das nicht.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 06.11.2007 22:54:37 von df4or

Frank Seitz wrote:

> Hallo zusammen,
>
> um in Programmen nicht immer Kaskaden von uses schreiben
> zu müssen, habe ich eine AUTOLOAD-Methode geschrieben,
> die ich in UNIVERSAL installiere, die beim ersten
> Methodenaufruf für eine Klasse das betreffende Modul
> automatisch lädt und dann die Methode aufruft. Code:
>
> package UNIVERSAL;
>
> sub AUTOLOAD {
> my $this = shift;
>
> my ($module,$sub) = our $AUTOLOAD =~ /^(.*)::(\w+)$/;
> return if $sub !~ /[^A-Z]/;
>
> eval "use $module";
> die $@ if $@;
>
> return $this->$sub(@_);
> }
>
> Scheint zu funktionieren.
>
> Es gibt auf CPAN Module, die dasselbe oder ähnliches tun.
> Ich habe mir diese nicht genauer angesehen, sie scheinen
> komplizierter zu sein. In einer Doku habe ich einen Kommentar
> gefunden, der mich nachdenklich macht:
>
> There are many other issues with AUTOLOAD that this module
> does not address. Primary among them is the fact that if
> you call a function that does not exist in a package that
> inherits from one with an AUTOLOAD, Perl will do a method search
> for that AUTOLOAD. This is why this module does not install
> AUTOLOAD in UNIVERSAL by default, and it is strongly
> suggested that you not do so either.
>
(http://search.cpan.org/~tilly/Class-AutoloadCAN-0.03/lib/Cl ass/AutoloadCAN.pm)
>
> Hat jemand eine Idee, was das angesprochene Problem
> mit AUTOLOAD in UNIVERSAL sein soll? Ich verstehe das nicht.

Ich kenne AUTOLOAD in UNIVERSAL nur aus der Theorie, aber den obenstehenden,
englischen Absatz verstehe ich so, das es durch Mehrfachvererbung zu
konkurrierenden Aufrufen von UNIVERSAL kommen könnte, wenn mehrere Packages
das (per default und ohne ausdrücklichen Hinweis darauf) implementieren.

Ich musste den Abschnitt aber auch fünfmal lesen, bevor ich den Sinn
verstanden habe. Evtl. feh t da das eine oder andere Komma. Vielleicht ist
es so einleuchtender:

Primary among them is the fact that,
if you call a function that does not exist,
in a package that inherits from one with an AUTOLOAD,
Perl will do a method search for that AUTOLOAD.
(2 Kommata von mir zugefügt).

This is why this module does not install
AUTOLOAD in UNIVERSAL by default, and it is strongly
suggested that you not do so either.

Da Perl den Vererbungsbaum zuerst in die Tiefe und dann erst in die Breite
durchsucht könnte es also vorkommen, das eine andere als deine
AUTOLOAD-Routine früher gefunden wird. Ob die dann das tut was Du
erwartest? Deswegen soll man solche Sachen wohl nicht per Default
verwenden, oder wenn, dann dick und fett darauf hinweisen.

Gruß,
Ekki

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 06.11.2007 23:20:32 von Frank Seitz

Ekki Plicht (DF4OR) wrote:
>
> Ich kenne AUTOLOAD in UNIVERSAL nur aus der Theorie, aber den obenstehenden,
> englischen Absatz verstehe ich so, das es durch Mehrfachvererbung zu
> konkurrierenden Aufrufen von UNIVERSAL kommen könnte, wenn mehrere Packages
> das (per default und ohne ausdrücklichen Hinweis darauf) implementieren.

Ähm, UNIVERSAL ist die Basisklasse aller Klassen. Was meinst du
damit, es könnte konkurrierende Aufrufe von UNIVERSAL geben und
mehrere Packages könnten "das" implementieren?

> Da Perl den Vererbungsbaum zuerst in die Tiefe und dann erst in die Breite
> durchsucht könnte es also vorkommen, das eine andere als deine
> AUTOLOAD-Routine früher gefunden wird. Ob die dann das tut was Du
> erwartest? Deswegen soll man solche Sachen wohl nicht per Default
> verwenden, oder wenn, dann dick und fett darauf hinweisen.

Das kann es nicht sein. Wenn eine Klasse (= Package) noch nicht
existiert, kann keine AUTOLOAD-Routine früher gefunden werden,
denn dann gibt es noch keine @ISA-Hierarchie für die Klasse.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 07.11.2007 22:20:25 von Slaven Rezic

"Ekki Plicht (DF4OR)" writes:

> Da Perl den Vererbungsbaum zuerst in die Tiefe und dann erst in die Breite
> durchsucht könnte es also vorkommen, das eine andere als deine
> AUTOLOAD-Routine früher gefunden wird.

Das ist kein Problem, weil der AUTOLOAD-Mechanismus erst verwendet
wird, wenn nichts Passendes in der gesamten Klassenhierarchie gefunden
wurde.

Aus perldoc perlobj:

| If neither the current class, its named base classes, nor the
| UNIVERSAL class contains the requested method, these three places are
| searched all over again, this time looking for a method named
| AUTOLOAD().

Gruß,
Slaven

--
Slaven Rezic - slaven rezic de

tktimex - time recording tool
http://sourceforge.net/projects/ptktools/

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 07.11.2007 23:34:42 von df4or

Slaven Rezic wrote:

> "Ekki Plicht (DF4OR)" writes:
>
>> Da Perl den Vererbungsbaum zuerst in die Tiefe und dann erst in die
>> Breite durchsucht könnte es also vorkommen, das eine andere als deine
>> AUTOLOAD-Routine früher gefunden wird.
>
> Das ist kein Problem, weil der AUTOLOAD-Mechanismus erst verwendet
> wird, wenn nichts Passendes in der gesamten Klassenhierarchie gefunden
> wurde.
>
> Aus perldoc perlobj:
>
> | If neither the current class, its named base classes, nor the
> | UNIVERSAL class contains the requested method, these three places are
> | searched all over again, this time looking for a method named
> | AUTOLOAD().

Ok, I stand corrected.

Gruß,
Ekki

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 08.11.2007 09:22:20 von Ferry Bolhar

Frank Seitz:

> Es gibt auf CPAN Module, die dasselbe oder ähnliches tun.
> Ich habe mir diese nicht genauer angesehen, sie scheinen
> komplizierter zu sein. In einer Doku habe ich einen Kommentar
> gefunden, der mich nachdenklich macht:

[...]

Ich habe vor etlichen Jahren mal ein (für mich) nicht erklärbares
Verhalten von AUTOLOAD in Zusammenhang mit Vererbung
entdeckt:

{
package Base;
sub AUTOLOAD {
print "AUTOLOAD: @_\n";
}
}

{
package Sub;
our @ISA = 'Base';
my $s = bless {}, __PACKAGE__; # Ruft AUTOLOAD auf!
}

Das Blessing ruft hierbei die AUTOLOAD-Funktion des
Base-Packages auf, obwohl im Code keinerlei Methoden-
oder Funktionsaufrufe vorkommen. Der AUTOLOAD-
Funktion wird (hier) die markierte Hashreferenz (d.h.,
das Objekt) als Argument übergeben; die $AUTOLOAD-
Variable ist undefiniert.

Kann das jemand erklären?

Zu deiner Frage noch:

In perldiag gibt es dazu eine Meldung, die mit den "many
other issues with AUTOLOAD" zu tun haben könnte. Sucht
nach der "Use of inherited AUTOLOAD for non-method %s"
Meldung; ich erspare mir hier das Zitieren. Vielleicht hängt das
damit zusammen?

Für mich sind AUTOLOAD (von Funktionen) und Vererbung
(von Methoden) zwei Dinge, die ich - schon mir zuliebe ;-) -
nicht durcheinander bringe.

Im Schreiben einer UNIVERSAL::AUTOLOAD Methode
sehe ich ansonsten kein unmittelbares Problem, da ja
AUTOLOAD erst dann zum Tragen kommt, wenn sonst
nichts in der Vererbungshiearchie gefunden wird. Der
einzige Design-Fehler der Perl-Entwickler ist IMHO, dass
ich den AUTOLOADS für Funktionen und denen für
Methoden unterschiedliche Namen gegeben hätte.

Vielleicht solltest du deine Anfrage auch nach comp.lang.
perl.misc richten?

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolhar-nordenkampf@wien.gv.at

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 08.11.2007 10:33:29 von Christian Winter

Ferry Bolhar schrieb:
> Frank Seitz:
>
>> Es gibt auf CPAN Module, die dasselbe oder ähnliches tun.
>> Ich habe mir diese nicht genauer angesehen, sie scheinen
>> komplizierter zu sein. In einer Doku habe ich einen Kommentar
>> gefunden, der mich nachdenklich macht:
>
> [...]
>
> Ich habe vor etlichen Jahren mal ein (für mich) nicht erklärbares
> Verhalten von AUTOLOAD in Zusammenhang mit Vererbung
> entdeckt:
>
> {
> package Base;
> sub AUTOLOAD {
> print "AUTOLOAD: @_\n";
> }
> }
>
> {
> package Sub;
> our @ISA = 'Base';
> my $s = bless {}, __PACKAGE__; # Ruft AUTOLOAD auf!
> }
>
> Das Blessing ruft hierbei die AUTOLOAD-Funktion des
> Base-Packages auf, obwohl im Code keinerlei Methoden-
> oder Funktionsaufrufe vorkommen. Der AUTOLOAD-
> Funktion wird (hier) die markierte Hashreferenz (d.h.,
> das Objekt) als Argument übergeben; die $AUTOLOAD-
> Variable ist undefiniert.

Welche Perl-Version? Ein "print $AUTOLOAD" in Base::AUTOLOAD
zeigt hier, dass nach Sub::DESTROY gesucht wird, wenn das
Objekt zerstört wird. Ansonsten sehe ich keine Aufrufe von
AUTOLOAD.

Viele Grüße
-Christian

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 08.11.2007 11:16:20 von Frank Seitz

Christian Winter wrote:
> Ferry Bolhar schrieb:
>>
>>Ich habe vor etlichen Jahren mal ein (für mich) nicht erklärbares
>>Verhalten von AUTOLOAD in Zusammenhang mit Vererbung
>>entdeckt:
>>
>>{
>> package Base;
>> sub AUTOLOAD {
>> print "AUTOLOAD: @_\n";
>> }
>>}
>>
>>{
>> package Sub;
>> our @ISA = 'Base';
>> my $s = bless {}, __PACKAGE__; # Ruft AUTOLOAD auf!
>>}
>>
>>Das Blessing ruft hierbei die AUTOLOAD-Funktion des
>>Base-Packages auf, obwohl im Code keinerlei Methoden-
>>oder Funktionsaufrufe vorkommen. Der AUTOLOAD-
>>Funktion wird (hier) die markierte Hashreferenz (d.h.,
>>das Objekt) als Argument übergeben; die $AUTOLOAD-
>>Variable ist undefiniert.
>
> Welche Perl-Version? Ein "print $AUTOLOAD" in Base::AUTOLOAD
> zeigt hier, dass nach Sub::DESTROY gesucht wird, wenn das
> Objekt zerstört wird. Ansonsten sehe ich keine Aufrufe von
> AUTOLOAD.

Richtig. Beim bless passiert gar nichts.
AUTOLOAD() wird angesprochen, wenn $s aus dem Scope geht und Perl
den Destruktor aufruft. Da dieser nicht existiert,
schlägt der Aufruf beim AUTOLOAD der Basisklasse auf.
Das ist korrekt so.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 08.11.2007 11:21:05 von Frank Seitz

Slaven Rezic wrote:
> "Ekki Plicht (DF4OR)" writes:
>>
>>Da Perl den Vererbungsbaum zuerst in die Tiefe und dann erst in die Breite
>>durchsucht könnte es also vorkommen, das eine andere als deine
>>AUTOLOAD-Routine früher gefunden wird.
>
> Das ist kein Problem, weil der AUTOLOAD-Mechanismus erst verwendet
> wird, wenn nichts Passendes in der gesamten Klassenhierarchie gefunden
> wurde.
>
> Aus perldoc perlobj:
>
> | If neither the current class, its named base classes, nor the
> | UNIVERSAL class contains the requested method, these three places are
> | searched all over again, this time looking for a method named
> | AUTOLOAD().

Stimmt zwar, AUTOLOAD kommt später dran. Die AUTOLOAD-Methode wird aber
auch entlang der Vererbungshierarchie gesucht, insofern ist
der ursprüngliche Einwurf schon richtig (auch wenn er in meinem
Anwendungsfall keine Rolle spielt).

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 08.11.2007 11:38:26 von Frank Seitz

Ferry Bolhar wrote:
>
> Im Schreiben einer UNIVERSAL::AUTOLOAD Methode
> sehe ich ansonsten kein unmittelbares Problem, da ja
> AUTOLOAD erst dann zum Tragen kommt, wenn sonst
> nichts in der Vererbungshiearchie gefunden wird. Der
> einzige Design-Fehler der Perl-Entwickler ist IMHO, dass
> ich den AUTOLOADS für Funktionen und denen für
> Methoden unterschiedliche Namen gegeben hätte.

Oder dass bei einem Funktionsaufruf die Klassenhierarchie
nicht durchlaufen wird. Finde ich verwunderlich,
dass man das macht. Dieser Bug ist wohl nicht so
leicht abzustellen, da alter Code auf dem Verhalten
aufbaut.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 09.11.2007 09:26:10 von Ferry Bolhar

Christian Winter:

> Welche Perl-Version? Ein "print $AUTOLOAD" in Base::AUTOLOAD
> zeigt hier, dass nach Sub::DESTROY gesucht wird, wenn das
> Objekt zerstört wird.

OK, an DESTROY hatte ich nicht gedacht. Dann macht das also Sinn,
weil das lexikalische $s am Scopeende ja verschwindet.

Allerdings ist bei mir $AUTOLOAD undefiniert - in Perl 5.8.6 und 5.8.8
(RH Linux ES 4). Sonst wäre ich vermutlich von selber auf DESTROY
gekommen. Ich bekomme bei einem "print $AUTOLOAD\n" nur

Use of uninitialized value $Base::AUTOLOAD in concatenation (.) or string

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolhar-nordenkampf@wien.gv.at

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 09.11.2007 12:45:05 von Frank Seitz

Ferry Bolhar wrote:
>
> Allerdings ist bei mir $AUTOLOAD undefiniert - in Perl 5.8.6 und 5.8.8
> (RH Linux ES 4). Sonst wäre ich vermutlich von selber auf DESTROY
> gekommen. Ich bekomme bei einem "print $AUTOLOAD\n" nur
>
> Use of uninitialized value $Base::AUTOLOAD in concatenation (.) or string

Dann machst du irgendwas falsch. $AUTOLOAD wird vom Interpreter
immer vor Aufruf von AUTOLOAD() gesetzt.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 09.11.2007 17:44:00 von Ferry Bolhar

Frank Seitz:

> Dann machst du irgendwas falsch. $AUTOLOAD wird vom Interpreter
> immer vor Aufruf von AUTOLOAD() gesetzt.

Tja, es ist interessant. Schreibt man wie du

package UNIVERSAL;
sub AUTOLOAD {...}

dann wird auch $AUTOLOAD gesetzt.

Schreibt man hingegen wie ich

sub UNIVERSAL::AUTOLOAD {...}

dann nicht.

Aufgerufen wird AUTOLOAD aber in beiden Fällen.

Interessant, nicht wahr?

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolhar-nordenkampf@wien.gv.at

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 09.11.2007 23:03:40 von Ch Lamprecht

Ferry Bolhar schrieb:
> Frank Seitz:
>
>
>>Dann machst du irgendwas falsch. $AUTOLOAD wird vom Interpreter
>>immer vor Aufruf von AUTOLOAD() gesetzt.
>
>
> Tja, es ist interessant. Schreibt man wie du
>
> package UNIVERSAL;
> sub AUTOLOAD {...}
>
> dann wird auch $AUTOLOAD gesetzt.
>
> Schreibt man hingegen wie ich
>
> sub UNIVERSAL::AUTOLOAD {...}
>
> dann nicht.
>
> Aufgerufen wird AUTOLOAD aber in beiden Fällen.
>
> Interessant, nicht wahr?
>
> LG, Ferry
>

Hallo,

funktioniert bei mir auch:

sub UNIVERSAL::AUTOLOAD {
print "AL: $UNIVERSAL::AUTOLOAD\n";
}


ChildClass::testmethod();


gibt aus:
Use of inherited AUTOLOAD for non-method ChildClass::testmethod() is deprecated
at test3.pl line 11.
AL: ChildClass::testmethod

Christoph

--
use Tk;use Tk::GraphItems;$c=tkinit->Canvas->pack;push@i,Tk::GraphItems ->
TextBox(text=>$_,canvas=>$c,x=>$x+=70,y=>100)for(Just=>anoth er=>Perl=>Hacker);
Tk::GraphItems->Connector(source=>$i[$_],target=>$i[$_+1])fo r(0..2);
$c->repeat(30,sub{$_->move(0,4*cos($d+=3.16))for(@i)});MainL oop

Re: Probleme mit AUTOLOAD in UNIVERSAL?

am 10.11.2007 14:12:51 von Frank Seitz

Ferry Bolhar wrote:
>
> Tja, es ist interessant. Schreibt man wie du
>
> package UNIVERSAL;
> sub AUTOLOAD {...}
>
> dann wird auch $AUTOLOAD gesetzt.
>
> Schreibt man hingegen wie ich
>
> sub UNIVERSAL::AUTOLOAD {...}
>
> dann nicht.
>
> Aufgerufen wird AUTOLOAD aber in beiden Fällen.
>
> Interessant, nicht wahr?

Ja, interessant, aber doch sonnenklar:
Der Package-Präfix gilt bei Deiner Vereinbarung für die
Subroutine, nicht für die in der Subroutine vorkommenden Variablen.
Du sprichst also die falsche $AUTOLOAD-Variable an.

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: Probleme mit AUTOLOAD in UNIVERSAL?

am 12.11.2007 18:00:29 von Ferry Bolhar

Frank Seitz:

> Ja, interessant, aber doch sonnenklar:
> Der Package-Präfix gilt bei Deiner Vereinbarung für die
> Subroutine, nicht für die in der Subroutine vorkommenden Variablen.
> Du sprichst also die falsche $AUTOLOAD-Variable an.

Ja, sonnenklar. Danke. Unklar ist hingegen, wo ich beim
Schreiben meinen Kopf hatte... ;-)

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolhar-nordenkampf@wien.gv.at