Fragen zu CORE:: und CORE::GLOBAL::

Fragen zu CORE:: und CORE::GLOBAL::

am 30.01.2007 16:13:13 von Ferry Bolhar

Hallo,

mir ist der Sinn der genannten speziellen Packages nicht ganz klar.

Angenommen, ich deklariere eine Funktion

sub sin {
my $arg = shift;
print "sin: $arg\n";
return $arg + $arg;
}
print sin(2);

Ich erhalte eine "Ambiguous call resolved as CORE::sin()" Warnung.
Schreibe ich CORE::sin(), wird der ganz normale Sinus berechnet.
Schreibe ich &sin(), wird meine Funktion aufgerufen. Soweit alles klar.

Deklariere ich die meine Funktion mit

use subs 'sin';

kann ich sie auch ohne & schreiben. Die Built-in Funktion bleibt nach
wie vor als CORE::sin ansprechbar.

Bis jetzt eigentlich nichts Neues, abgesehen, dass ich auch

sub CORE::sin {
return "CORE::sin";
}

schreiben kann. Jetzt wird beim Aufruf von CORE::sin() die
eingebaute, bei &CORE::sin() hingegen die definierte Funktion
aufgerufen.

Was ist aber jetzt der Zweck von CORE::GLOBAL::?

Deklarier ich eine Funktion

sub CORE::GLOBAL::sin {
return "CORE::GLOBAL::sin";
}

kann ich sie mit &CORE::GLOBAL::sin() aufrufen, mit
CORE::GLOBAL::sin() hingegen erhalten ich bereits beim
Kompilieren die Meldung

"CORE::GLOBAL is not a keyword"

Was ist der Zweck von CORE::GLOBAL::?

Danke & LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at

Re: Fragen zu CORE:: und CORE::GLOBAL::

am 30.01.2007 17:39:38 von Frank Seitz

Ferry Bolhar wrote:

> Was ist der Zweck von CORE::GLOBAL::?

Steht in perlsub, einschließlich Beispiel.

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: Fragen zu CORE:: und CORE::GLOBAL::

am 31.01.2007 15:03:47 von Ferry Bolhar

Frank Seitz:

>> Was ist der Zweck von CORE::GLOBAL::?
>
> Steht in perlsub, einschließlich Beispiel.

Danke, Frank! In perltoc habe ich leider nichts darüber gefunden, daher
wusste ich nicht, wo ich suchen sollte (jetzt habe ich ein Skript
geschrieben,
das alle Files in /usr/lib/perl5/*.pod nach einem gegebenen Zeichenmuster
durchsucht, da sollte das nicht mehr passieren).

Ich fasse kurz zusammen:

Man kann in Perl fast alle Keywords mit eigenen Funktionen überschreiben.
Ausgenommen davon sind einige spezielle, die für Deklarationen (my, our,
package, use, no, format, sub) oder als Befehls-Modifier bzw. zur
Konstruktion
von zusammengesetzten Befehlen und Schleifen (if, unless, while, until, for,
foreach, else, elsif, redo, last, next, return) verwendet werden, sowie
Befehle
mit spezieller Syntax (goto, grep, local, map, sort, defined, exists, q, qq,
qw,
qx, qr, tr, m, s, y, study, split, print, fprint, pos, eval, scalar, undef,
tie, tied,
untie).

Um dem Compiler klar zu machen, welche Funktion (eigene oder built-in)
man aufrufen will, muss man die Funktion entweder vor dem ersten Aufruf
mit

use subs '';

deklarieren oder ihr beim Aufruf ein "&" vorsetzen.

- Unabhängig davon kann man durch Vorsetzen von CORE:: immer noch
auf das Perl-Builtin zugreifen, zB:

use subs 'sin';
sub sin { ... }

print sin($y); # Eigenes sin
print CORE::sin($y); # Perl's sin

Ein Deklaration

sub sin {...}

hat nur Auswirkungen auf das aktuelle Package, d.h., es ist nur die
aktuelle Symboltabelle (meistens 'main') davon betroffen. In anderen
Packages spricht 'sin' nach wie vor die eingebaute Funktion an. Dies
kann man durch Importieren der Funktion in das Pseudo-Package
CORE::GLOBAL umgehen:

BEGIN {
*CORE::GLOBAL::sin = \&sin;
}
sub sin {...}

print sin($y); # Eigenes sin
package Hugo;
print sin($y); # Immer noch eigenes sin
print CORE::sin($y); # Immer noch Perl's sin

Das entspricht der Deklaration einer Methode im Pseudo-Package
UNIVERSAL. Das Deklarieren der eigenen Funktion mit 'use subs'
kann hier entfallen.

Wichtig ist, dass das Importing (das man bei Modulcode natürlich
auch vom Exporter durchführen lassen kann), _vor_ dem ersten
Verwenden der überschriebenen Funktion passiert, damit der
Compiler den Code auf die überschriebenen Funktion anstelle
des Builtins generieren kann. Daher muss man die obige Typeglob-
Zuweisung in einen BEGIN-Block setzen (oder man läßt es den
Exporter machen, der im Context eines BEGIN-Blocks abläuft).

Wichtig ist auch, dass ein Importing durchgeführt wird - eine
Deklaration

sub CORE::GLOBAL::sin {...}

wird nicht als importiert erkannt und daher ignoriert (es wird vom
Compiler weiterhin die Builtin-Funktion verwendet).

Der Trick mit CORE::GLOBAL funktioniert allerdings nur für
Builtins - ein

sub hugo {...}
BEGIN {
*CORE::GLOBAL::hugo = \&hugo;
}
wird zwar vom Compiler anstandslos geschluckt, aber ansonsten
ignoriert - die Funktion hugo() ist nach wie vor nur in dem Package,
in dem sie deklariert wurde, definiert (eigentlich schade, dass man
dieses Verhalten nicht einstellen kann).

Das Deklarieren eigener Funktionen in Package CORE

sub CORE::hugo {...}

ist zwar erlaubt, man muss die Funktion aber später mit führendem
'&' aufrufen:

print &CORE::hugo(...);

da der Parser sich sonst mit einem

CORE::hugo is not a keyword

beschwert. Davon abgesehen aber ist CORE ein Package wie jedes
andere, daher kann man auch - obwohl sicher nicht empfehlenswert -

package CORE;
print hugo(...); # ohne &

schreiben.

Bei der 'prototype' Funktion muss man für Builtins immer CORE::
vorsetzen, sonst wird eine benutzer-definierte Funktion angenommen,
selbst wenn keine solche existiert.

So, ich glaube, das ist wohl alles, was zu CORE und CORE::GLOBAL
zu sagen ist. Korrekturen und Ergänzungen sind wie immer willkommen.

Schöne Grüße,

Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at