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.
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
Code unten:
%Vor%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:
X wurde überhaupt nicht deklariert (Symboltabelleneintrag existiert nicht)
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
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%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.
Tags und Links perl variables declaration