STRESZCZENIE
W tym momencie, po dość intensywnych badań, jestem twardym stanowisku, że w sytuacji, gdy wpis w tablicy symboli z nazwą „X” został ogłoszony, ale nie przypisanego jest niemożliwe do ogólnego odróżnienia, który z typów odniesienia w glob został faktycznie zadeklarowany bez użycia głębokiego sondowania Devel :: stuff.
Innymi słowy, można powiedzieć tylko następujące 2 odrębne sytuacje:
X nie został zadeklarowany w ogóle (wpis w tablicy symboli nie istnieje)
X został ogłoszony, a niektóre typy globów zostały faktycznie przypisane.
W tym drugim przypadku,
Ty może znaleźć jakie rodzaje glob zostały przydzielone, a które nie były
Ale, nie może dowiedzieć się, które z nieprzepisane do globu typy zostały zadeklarowane, a nieprzypisane, które nie zostały w ogóle zadeklarowane.
Innymi słowy, dla our $f = 1; our @f;
; możemy stwierdzić, że $main::f
jest skalarem; , ale nie możemy stwierdzić, czy zostały zadeklarowane @f
i %f
- nie da się tego odróżnić od our $f = 1; our %f;
.
Należy pamiętać, że definicje podprogramów są również zgodne z tą drugą regułą, ale deklarowanie nazwy subdomena automatycznie przypisuje jej wartość (blok kodu), więc nigdy nie można mieć nazwy podrzędnej w "zadeklarowanej, ale nieprzypisanej" stan (uwaga: może nie być prawdą w przypadku prototypów - nie ma pojęcia).
ORIGINAL ODPOWIEDŹ
Cóż, bardzo ograniczona (i IMHO nieco kruchy) rozwiązanie do odróżnienia skalar z podprogramu może być użycie UNIVERSAL :: mogą:
use strict;
our $f;
sub g {};
foreach my $n ("f","g","h") {
# First off, check if we are in main:: namespace,
# and if we are, that we are a scalar
no strict "refs";
next unless exists $main::{$n} && *{"main::$n"};
use strict "refs";
# Now, we are a declared scalr, unless we are a executable subroutine:
print "Declared: \$$n\n" unless UNIVERSAL::can("main",$n)
}
Rezultat :
Declared: $f
Uwaga: {SCALAR}
wydaje się nie działać, aby wyleczyć nie-skalary w moim testowaniu - szczęśliwie przeszedł przez @A
i %H
, gdy je zadeklarowałem i dodałem do pętli.
UPDATE
Próbowałem podejście Brian d Foy jest z rozdziałem 8 „Mastering Perl” i jakoś nie był w stanie zmusić go do pracy dla skalarów, skrótów lub tablice; ale jak wspomniano poniżej draegtun działa dla podprogramów lub zmiennych , które zostały przypisane do już:
> perl5.8 -we '{use strict; use Data::Dumper;
our $f; sub g {}; our @A=(); sub B{}; our $B; our %H=();
foreach my $n ("f","g","h","STDOUT","A","H","B") {
no strict "refs";
next unless exists $main::{$n};
print "Exists: $n\n";
if (defined ${$n}) { print "Defined scalar: $n\n"};
if (defined @{$n}) { print "Defined ARRAY: $n\n"};
if (defined %{$n}) { print "Defined HASH: $n\n"};
if (defined &{$n}) { print "Defined SUB: $n\n"};
use strict "refs";}}'
Exists: f
Exists: g
Defined SUB: g <===== No other defined prints worked
Exists: STDOUT
Exists: A
Exists: H
Exists: B
Defined SUB: B <===== No other defined prints worked
+1, i zwykle nie pobudzam stringish eval() s. :) To jest mniej więcej moje obecne podejście. Co ważne, sprawdzanie eval tutaj * nie * wywołuje metody FETCH tie() d skalar - to byłoby No Good (tm). Zastanawiam się, czy lokalne() izing $ SIG {__ WARN__} może zająć się komunikatami o błędach? – pilcrow
Tak, FWIW, w moich próbach jeśli zlokalizować _ \ _ WARN \ _ \ _ obsługi (i $ @ też z grzeczności) przed eval, ciszę błędy bez deskryptora pliku duppery. – pilcrow