Verhalten unklar, warum funktioniert das?

Verhalten unklar, warum funktioniert das?

am 17.05.2006 23:26:21 von Torsten Mohr

Hallo,

das unten stehende Skript ist nicht wirklich sinnvoll,
es ist beim Ausprobieren entstanden.

Was mich wundert ist daß:
- das "END;" keinen Fehler bringt
- das "ABC" einen Wert hat

Kann mir jemand das Verhalten erklären?
Vermutung:
- Das "use constant" wird am Anfang ausgeführt,
trotz dem es im "END" steht.
- das "END;" ruft "sub END" auf und damit hat
ABC einen Wert.


Danke für Tips,
Torsten.


#! /usr/bin/perl -w

use strict ( 'vars', 'subs', 'refs' );

my $abc = 1;

END;

sub END {
  use constant ABC => 8;
}


my $slink = 'abc';
#$$slink = ABC + 1_000;
$abc = ABC + 1_000;

print "abc $abc\n";

Re: Verhalten unklar, warum funktioniert das?

am 18.05.2006 01:35:30 von Wolf Behrenhoff

Torsten Mohr schrieb:
> Hallo,
>
> Kann mir jemand das Verhalten erklären?
> Vermutung:
> - Das "use constant" wird am Anfang ausgeführt,
> trotz dem es im "END" steht.

Wenn etwas unter "use" steht, dann ist es ähnlich wie ein BEGIN-Block
anzusehen und wird sofort ausgeführt. Erst nachdem alles abgearbeitet
wurde, startet das normale Programm. Es ist also egal, wo das use
constant steht und ob es überhaupt in einem Bereich steht, der
ausgeführt wird -- wichtig ist nur, dass es vor der Verwendung der
Variablen steht.

Einfaches Beispiel - der Block mit use... wird nicht ausgeführt, dennoch
ist C bekannt:

if (0) { use constant C => 1234; }
print C;

Guck dir auch mal perldoc -f use an.

Wolf

Re: Verhalten unklar, warum funktioniert das?

am 18.05.2006 12:01:08 von Ferry Bolhar

Torsten Mohr/Wolf:

> > Kann mir jemand das Verhalten erklären?
> > Vermutung:
> > - Das "use constant" wird am Anfang ausgeführt,
> > trotz dem es im "END" steht.

Das ist richtig.

> Wenn etwas unter "use" steht, dann ist es ähnlich wie ein BEGIN-Block
> anzusehen und wird sofort ausgeführt

Es wird tatsächlich als BEGIN-Block kompiliert und ausgeführt.

>. Erst nachdem alles abgearbeitet
> wurde, startet das normale Programm. Es ist also egal, wo das use
> constant steht und ob es überhaupt in einem Bereich steht, der
> ausgeführt wird

Es ist egal, solange es keine anderen BEGIN-Blöcke gibt, auf die
es Auswirkungen haben könnte. In diesem Beispiel ist es daher
egal. Es gibt Fälle, wo das nicht so ist - vor allem, wenn es sich
um Compiler-Pragmas handelt, die u.U. aufeinander Einfluss
haben, oder wenn entsprechender XS-Code ausgeführt wird.

> Einfaches Beispiel - der Block mit use... wird nicht ausgeführt, dennoch
> ist C bekannt:
>
> if (0) { use constant C => 1234; }
> print C;

Es hilft, sich ein "use" als "require"/"import" in einem BEGIN-Block
(das genau ist es nämlich) vorzustellen, dh., in diesem Beispiel:

if (0) {
BEGIN {
require constant;
constant->import(C => 1234);
}
}

Nachdem der BEGIN-Block ausgeführt wurde, wird sein Code
entfernt, übrig bleibt also:

if (0) {}

und das wird im Rahmen der Optimierungsphase entfernt (es wird
zu einem Null-OP = No Operation umgewandelt).

LG, Ferry

--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol@adv.magwien.gv.at

Re: Verhalten unklar, warum funktioniert das?

am 18.05.2006 18:49:37 von Torsten Mohr

Hallo,

danke für die Tips.

Ich suche noch nach einer Erklärung, was das "END;" bewirkt.
Ruft das die "sub END { }" auf?

> Was mich wundert ist daß:
> - das "END;" keinen Fehler bringt
> - das "ABC" einen Wert hat
>
> Kann mir jemand das Verhalten erklären?
> Vermutung:
> - Das "use constant" wird am Anfang ausgeführt,
> trotz dem es im "END" steht.
> - das "END;" ruft "sub END" auf und damit hat
> ABC einen Wert.


Grüße,
Torsten.

Re: Verhalten unklar, warum funktioniert das?

am 18.05.2006 19:08:06 von Ch Lamprecht

Torsten Mohr schrieb:
> Hallo,
>
> danke für die Tips.
>
> Ich suche noch nach einer Erklärung, was das "END;" bewirkt.
> Ruft das die "sub END { }" auf?
>
>
>>Was mich wundert ist daß:
>>- das "END;" keinen Fehler bringt
>>- das "ABC" einen Wert hat
>>
>>Kann mir jemand das Verhalten erklären?
>>Vermutung:
>>- Das "use constant" wird am Anfang ausgeführt,
>> trotz dem es im "END" steht.
>>- das "END;" ruft "sub END" auf und damit hat
>> ABC einen Wert.

Hallo,

mach doch mal ein 'perl -MO=Deparse script.pl' ...

Christoph

--

perl -e "print scalar reverse q/ed.enilno@ergn.l.hc/"

Re: Verhalten unklar, warum funktioniert das?

am 19.05.2006 15:54:25 von Ferry Bolhar

Torsten Mohr:

> Ich suche noch nach einer Erklärung, was das "END;" bewirkt.
> Ruft das die "sub END { }" auf?

Nein.

> > Was mich wundert ist daß:
> > - das "END;" keinen Fehler bringt

"END" ist (wie auch BEGIN, INIT, CHECK, AUTOLOAD und
DESTROY) ein reservierter Funktionsname. Solchen Namen kann
man ein "sub" voranstellen, da ist aber optional. Da kein Block
angegeben ist, wird dein "END;" schlicht und einfach als

sub END;

interpretiert, dh., die Deklaration einer Funktion names END. Das
ist nicht verboten, und daher gibt's auch keinen Fehler.

Solche speziellen Funktionen (eigentlich Blöcke) kann man selbst nicht
aufrufen, sondern sie werden von Perl aufgerufen, wenn der Zeitpunkt
hierfür gekommen ist.

Hättest du statt "END" ein anderes Wort (zB. "EEND") genommen,
hättest du mit "use strict" die Meldung

Bareword "EEND" not allowed while "strict subs" in use

bekommen (weil dann der Aufruf aufscheint, bevor die entsprechende
Subroutine mit "sub EEND {...}" deklariert wird und der Compiler
somit mit "EEND" nichts anfangen kann).

> > - das "ABC" einen Wert hat

Wie bereits erwähnt, ist "use" eine Compilerdirektive, die wie ein
BEGIN-Block ausgeführt wird, egal wo das "use" jetzt steht. Dass es
in deinem Beispiel in einem END-Block steht, ist daher vollkommen
irrelevant, es (und der Code des aufgerufenen Moduls) wird ausgeführt,
sobald der Compiler beim Einlesen des Scripts darauf stößt. Und
daher ist "ABC" schon definiert, bevor dein Skript losläuft.

"use constant" selbst richtet eine anonyme Subroutine und den
Typeglob, der darauf zeigt, ein. In deinem Beispiel wäre das

*main::ABC = sub () {8};

Das ist eine sog. Konstant-Funktion (dh., sie übernimmt keine
Parameter und der Funktionskörper enthält nur ein Literal), deren
Aufrufe in einer der späteren Compilerphasen (dem "Constant
Folding") durch Einsetzen der Konstante wegoptimiert wird. Aus

print ABC;

wird also bereits beim Compilieren

print 8;

Mit dem Deparse-Modul kann man sich das sehr schön ansehen.

HTH & LG, Ferry

--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol@adv.magwien.gv.at

Re: Verhalten unklar, warum funktioniert das?

am 19.05.2006 18:10:25 von Torsten Mohr

Hallo,

danke für die Erklärung, das hilft mir weiter und klärt meine
Fragen restlos.


Danke,
Torsten.