Deklarierte deklarierte Paketvariablen in Perl

8

Gegeben

%Vor%

Wie kann ich feststellen, dass $f , aber nicht $g deklariert wurde? Aus dem Stegreif dachte ich, dass *{main::g}{SCALAR} undefiniert sein könnten, aber es ist ein bona fide SCALAR Ref.

Hintergrund: Ich möchte eine Variable in main:: importieren, aber karpfen oder krächzen, wenn diese Variable bereits deklariert ist.

BEARBEITEN Es wurde eine f Subroutine als Reaktion auf die erste Antwort von @ DVK hinzugefügt.

ANTWORT (2010-07-27)

Das ist nicht einfach, aber es ist möglich.

eval technique ist am tragbarsten, Arbeiten an Perls älter als 5.10. In neueren Perls, introspektive Module wie Devel::Peek und B kann diskriminieren.

    
pilcrow 26.07.2010, 13:52
quelle

5 Antworten

1

Ich gab mein Bestes und ging sogar so weit, zu versuchen, eval STRING zu fragen, ob $main::f über our oder my deklariert wurde. (Dies erforderte das Duplizieren, Schließen und spätere Wiederherstellen von STDERR , um die Chattyness zu reduzieren.) Sobald Sie Pakete geändert haben, scheinen diese Deklarationen bei einer temporären Switchback-Funktion nicht mehr sichtbar zu sein.

Die folgende Technik erkennt, ob $f über

deklariert wurde %Vor%

Code unten:

%Vor%     
Greg Bacon 26.07.2010, 16:23
quelle
4

ZUSAMMENFASSUNG

An dieser Stelle bin ich der festen Überzeugung, dass in einer Situation, in der ein Symboltabelleneintrag mit dem Namen "X" deklariert, aber nicht zugewiesen wurde, es nicht möglich ist, generisch zu unterscheiden welcher der Referenztypen in einem Glob wurde eigentlich deklariert, ohne Devel :: stuff zu verwenden.

Mit anderen Worten, Sie können nur die folgenden zwei verschiedenen Situationen unterscheiden:

  1. X wurde überhaupt nicht deklariert (Symboltabelleneintrag existiert nicht)

  2. X wurde deklariert und einige der Glob-Typen wurden tatsächlich zugewiesen.

    In diesem zweiten Fall

    • Sie können finden, WELCHE der Glob-Typen zugewiesen wurden und welche nicht

    • waren
    • ABER, Sie können nicht herausfinden, welche der nicht zugewiesenen Globs-Typen deklariert und nicht zugewiesen wurden und welche nicht deklariert wurden.

    Mit anderen Worten, für our $f = 1; our @f; ; wir können sagen, dass $main::f ein Skalar ist; aber wir können nicht sagen, ob @f und %f deklariert wurden oder nicht - es ist überhaupt nicht von our $f = 1; our %f; unterscheidbar.

    Bitte beachten Sie, dass die Subroutinen-Definitionen auch dieser zweiten Regel folgen, aber das Deklarieren eines benannten Subs weist ihm automatisch einen Wert zu (den Code-Block), so dass Sie niemals einen Sub-Namen in einem "deklariert, aber nicht zugewiesen" Status haben können (Vorbehalt: ist vielleicht nicht wahr für Prototypen? keine Ahnung).

ORIGINAL ANTWORT

Nun, sehr begrenzte (und IMHO etwas fragile) Lösung, um einen Skalar von einer Subroutine zu unterscheiden, könnte UNIVERSAL :: can:

sein %Vor%

Ergebnis:

%Vor%

Bitte beachten Sie, dass {SCALAR} anscheinend nicht funktioniert, um Nicht-Skalare in meinen Tests auszusortieren - sie hat glücklicherweise @A und %H passiert, wenn ich sie deklariert und der Schleife hinzugefügt habe.

AKTUALISIEREN

Ich habe brian d foy's Ansatz aus Kapitel 8 von "Mastering perl" versucht und war irgendwie nicht in der Lage, es für Skalare, Hashes oder Arrays zu verwenden; aber wie unten von draegtun beschrieben, funktioniert es für Subroutinen oder für Variablen , die bereits zugewiesen wurden:

%Vor%     
DVK 26.07.2010 14:45
quelle
3

Ältere Perls (vor 5.10) haben immer etwas im Skalar-Slot.

Bei neueren Perls scheint es so, als ob das alte Verhalten nachgeahmt wurde Versuche, * FOO {SCALAR} zu machen.

Sie können das B-Introspektionsmodul jedoch verwenden, um den Skalarsteckplatz zu überprüfen:

%Vor%     
ysth 26.07.2010 16:55
quelle
1

Devel :: Peek scheint in der Lage zu sein, zwischen benutzten und unbenutzten Dingen im SCALAR-Slot zu unterscheiden:

%Vor%

Die Ausgabe ist:

%Vor%

Die interessierenden Zeilen befinden sich im Abschnitt GP = , insbesondere SV, AV, HV und CV (Skalar, Array, Hash und Code). Beachten Sie, dass der Speicherauszug von *g SV = 0x0 anzeigt. Leider scheint es keinen programmatischen Weg zu geben, um diese Information zu erhalten. Ein stumpfer Instrumentenansatz wäre, die Ausgabe von Dump() zu erfassen und zu parsen.

    
Michael Carman 26.07.2010 15:52
quelle
0

Sie können nach einem definierten Unterprogramm wie folgt suchen:

%Vor%

Leider funktioniert dieselbe Methode nur für die Paketvariable, wenn ein Wert zugewiesen wurde:

%Vor%

/ I3az /

    
draegtun 26.07.2010 15:28
quelle

Tags und Links