Keinen Fehlermeldung wenn Funktion nicht vorhanden?
Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 10.08.2006 14:20:13 von j-w-b
Hallo NG,
folgende Frage hätte ich. Warum bekomme ich nicht gleich beim Ausführen
eines Scripts eine Fehlermeldung von Perl wenn eine Funktion die ich aufrufe
überhaupt nicht vorhanden ist? Mache ich was falsch oder ist das normal das
ich dann erst eine Fehlermeldung bekomme wenn Perl auf die Funktions
zugreifen will?
Danke und
mit herzlichen Grüßen
Joachim Böcker
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 10.08.2006 15:02:16 von Christian Winter
Joachim Böcker schrieb:
> folgende Frage hätte ich. Warum bekomme ich nicht gleich beim Ausführen
> eines Scripts eine Fehlermeldung von Perl wenn eine Funktion die ich aufrufe
> überhaupt nicht vorhanden ist? Mache ich was falsch oder ist das normal das
> ich dann erst eine Fehlermeldung bekomme wenn Perl auf die Funktions
> zugreifen will?
Das liegt in der Natur von Perl begründet, dass Funktionen auch
zur Laufzeit aus externen Quellen geladen (oder anderweitig
dynamisch erzeugt) werden können. Ein kleines Beispiel, das das
Konzept hoffentlich verständlich erläutert:
-------- Datei lala.pl -------
sub lala {
print "lala".$/;
}
------------------------------
-------- Datei lolo.pl -------
sub lolo {
print "lolo".$/;
}
------------------------------
---------- demo.pl -----------
#!/usr/bin/perl
use strict;
use warnings;
use FindBin qw($Bin); # $Bin enthält den Pfad zum Perl-Script
exit unless( @ARGV && -e "$Bin/$ARGV[0].pl" );
eval 'do "$Bin/$ARGV[0].pl"';
print "...die Spannung steigt...".$/;
lala();
-------------------------------
Hier lädt Perl mittels "eval EXPR" und "do()" die Funktion dynamisch
aus einer Datei, deren Name (ohne .pl-Erweiterung) über die
Kommandozeile übergeben wird. Das Skript muss also schonmal bis zur
do()-Zeile gelaufen sein, bis Perl sicher sein kann, ob die Funktion
vorhanden ist.
C:\> demo.pl lala
....die Spannung steigt...
lala
C:\> demo.pl lolo
....die Spannung steigt...
Undefined subroutine &main::lala called at C:\demo.pl line 11
(Bei einem String-eval wird der Code erst zur Ausführungszeit der
Zeile geparst, deshalb darf Perl vorher noch gar nicht wissen, ob
in dieser Zeile die danach aufgerufene Funktion schon existiert
oder nicht, siehe "perldoc -f eval".)
Eine konkrete Anwendung dafür ist z.B. häufig in Content-Management-
Systemen zu finden, wo Codeteile in einer Datenbank abgelegt und
erst zur Laufzeit geholt und eingebunden werden.
HTH
-Christian
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 16.08.2006 15:52:54 von Ferry Bolhar
Joachim Böcker:
> folgende Frage hätte ich. Warum bekomme ich nicht gleich beim Ausführen
> eines Scripts eine Fehlermeldung von Perl wenn eine Funktion die ich
aufrufe
> überhaupt nicht vorhanden ist?
Weil der Compiler, der auf den Funktionsaufruf trifft, nicht wissen kann,
ob, wann und wie die Funktion später (zur Laufzeit) definiert sein wird
(oder ob du sie gar nicht definieren und stattdessen den AUTOLOAD-
Mechanismus verwenden wirst).
> Mache ich was falsch oder ist das normal das
> ich dann erst eine Fehlermeldung bekomme wenn Perl auf die Funktions
> zugreifen will?
Du machst nichts falsch, das ist einfach eine Eigenheit einer Sprache,
in der man zB. mit
*neueFunktion = sub {....};
sogar zur Laufzeit - dh. längst, nachdem der Compiler seine Arbeit
beendet hat - noch Funktionen (nach)definieren kann.
Ich finde, dass gerade das eines der Merkmale ist, das Perl zu einer
interessanten Sprache macht.
LG, Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol@adv.magwien.gv.at
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 18.08.2006 02:13:49 von j-w-b
> *neueFunktion = sub {....};
> Ich finde, dass gerade das eines der Merkmale ist, das Perl zu einer
> interessanten Sprache macht.
Danke vielmals für die Erklärungen, aber wo kann man sowas gebrauchen?
Gruß
Joachim
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 18.08.2006 08:47:52 von Slaven Rezic
"Joachim Böcker" writes:
> > *neueFunktion = sub {....};
> > Ich finde, dass gerade das eines der Merkmale ist, das Perl zu einer
> > interessanten Sprache macht.
>
> Danke vielmals für die Erklärungen, aber wo kann man sowas gebrauchen?
>
Z.B. zur automatischen Accessor-Erstellung oder zum Nachladen von Code
(Plugins).
Gruß,
Slaven
--
Slaven Rezic - slaven rezic de
Berlin Perl Mongers - http://berlin.pm.org
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 18.08.2006 10:37:54 von Ferry Bolhar
Joachim Böcker:
>> *neueFunktion = sub {....};
>> Ich finde, dass gerade das eines der Merkmale ist, das Perl zu einer
>> interessanten Sprache macht.
>
> Danke vielmals für die Erklärungen, aber wo kann man sowas gebrauchen?
Damit kann man zB.recht einfach Code schreiben, der "Wrapper"-
Routinen für andere Routinen erstellt:
sub do_log {
no strict 'refs';
my $name = caller() . '..' . shift;
my $oldsub = *$name{CODE} or die "Cant't find subroutine '$name'!\n";
my $newsub = sub {
my ($pkg, $file, $line) = caller;
print STDERR "$name(@_) called from '$pkg', file '$file', line $line\n";
goto $oldsub;
};
*$name = $newsub;
}
sub hello() {
...
}
do_log('hello'); # hello() gibt nun aus, wer es aufgerufen hat
Die Subroutine do_log richtet einen Wrapper für die als Argument
angegebene Funktion ein, indem sie zunächst aus dem jeweiligen Typeglob
die Referenz auf die Funktion ($oldsub) ermittelt und anschließend eine
neue Funktion ($newsub), die vor dem Aufruf der alten eine entsprechende
Meldung auf STDERR ausgibt, einrichtet. Das Intereassante dabei ist,
dass die neue Funktion unter demselben Namen wie die Alte angesprochen
wird, dass daher Code, der darauf zugreift, nicht geändert werden muss.
Er "weiß" gar nicht, dass nun eine Wrapper-Funktion statt der ursprünglichen
Funktion aufgerufen wird. Das bietet eine Vielzahl an Debugging- und
Tracingmöglichkeiten.
Ein anderes Beispiel für so etwas ist Code, der - von dem jeweiligen
Environment abhängig - gleichnamige Routinen mit unterschiedlicher
Funktionalität bereitstellt. Anstatt bei jedem Aufruf der Routine das
Environment zu prüfen und dann in den jeweiligen Codeteil zu dispatchen,
geschieht dies nur einmal - beim Start. Danach wird die jeweilige Routine,
wie oben gezeigt, "generiert" (oder "require'd") und stets unter demselben
Namen bekannt gemacht. Code, der diese Routine dann unter diesem Namen
aufruft, kann in allen Environments eingesetzt werden, wobei weder der Code
selber, noch der Code zum Generieren oder Laden angepasst werden muss.
Weil die Environment-Prüfung nur einmal abläuft, ist er außerdem schneller.
Wir verwenden das u.a. für das Command Line Handling für Code, der
unter UNIX, aber auch unter VMS (wo zB. eine Befehlszeile ganz anderes
aussieht und die Getopt:: Module nicht funktionieren) laufen soll.
PS: Das "no strict 'refs'" ist notwendig, weil in "*$name" die Variable
$name
einen Namen und keine Referenz (dh., eine "symbolische Referenz") enthält,
was mit "use strict"'refs'" bzw. mit "use strict" nicht erlaubt wäre.
LG, Ferry
--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol@adv.magwien.gv.at
Re: Keinen Fehlermeldung wenn Funktion nicht vorhanden?
am 18.08.2006 17:37:43 von Ferry Bolhar
Ich schrieb:
> my $name = caller() . '..' . shift;
und meint natürlich
my $name = caller() . '::' . shift;
Sorry & LG,
Ferry
>
> --
> Ing. Ferry Bolhar
> Municipality of Vienna, Department 14
> A-1010 Vienna / AUSTRIA
> E-mail: bol@adv.magwien.gv.at
>
>