TÓM TẮT
Tại thời điểm này, sau khi nghiên cứu khá rộng, tôi một quan điểm vững chắc rằng trong một tình huống khi một mục bảng biểu tượng với tên chữ "X" đã kê khai nhưng không giao cho, nó là không thể phân biệt phổ biến loại tham chiếu nào trong một glob thực sự được khai báo bằng cách sử dụng thăm dò sâu của công cụ Devel ::.
Nói cách khác, bạn có thể nói chỉ có 2 tình huống riêng biệt sau:
X đã không được công bố tại tất cả (entry bảng symbol không tồn tại)
X được tuyên bố và một số các loại glob đã được gán cho.
Trong trường hợp thứ nhì này,
Bạn thể tìm MÀ các loại glob đã được giao cho và đó không phải là
NHƯNG, bạn không thể con số ra của các loại glob không được gán cho đã được khai báo và chưa được gán so với các loại không được khai báo.
Nói cách khác, đối với our $f = 1; our @f;
; chúng ta có thể nói rằng $main::f
là một vô hướng; nhưng chúng tôi KHÔNG thể nói liệu @f
và %f
có được khai báo hay không - nó hoàn toàn không phân biệt được với số our $f = 1; our %f;
. Xin lưu ý rằng các định nghĩa chương trình con cũng tuân thủ quy tắc thứ hai này, nhưng việc khai báo một tên được đặt tên sẽ tự động gán cho nó một giá trị (khối mã), vì vậy bạn không bao giờ có tên phụ trong "khai báo nhưng không được gán cho" nhà nước (caveat: có thể không đúng đối với nguyên mẫu ??? không có đầu mối).
ORIGINAL ĐÁP
Vâng, rất hạn chế (và IMHO hơi mong manh) giải pháp cho việc phân biệt một vô hướng từ một chương trình con có thể được sử dụng UNIVERSAL :: có thể:
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)
}
quả :
Declared: $f
Xin lưu ý rằng {SCALAR}
dường như không hoạt động để loại bỏ phi vô hướng trong thử nghiệm của tôi - nó vui vẻ được chuyển qua @A
và %H
nếu tôi tuyên bố chúng và thêm vào vòng lặp.
CẬP NHẬT
tôi đã cố gắng tiếp cận brian d Foy từ Chương 8 của "Mastering perl" và bằng cách nào đó đã không thể có được nó để làm việc cho vô hướng, băm hoặc mảng; nhưng như đã nói ở dưới đây bởi draegtun nó hoạt động cho chương trình con hoặc cho các biến đó đã được giao cho đã:
> 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, và tôi không bình thường upvote stringish() s. :) Đây là cách tiếp cận hiện tại của tôi nhiều hơn hoặc ít hơn. Quan trọng hơn, việc kiểm tra eval ở đây * không * gọi phương thức FETCH của tie() d vô hướng - đó là No Good (tm). Tôi tự hỏi, có thể local() izing $ SIG {__ WARN__} xử lý các thông báo lỗi? – pilcrow
Có, FWIW, trong thử nghiệm của tôi nếu bạn bản địa hóa _ \ _ WARN \ _ \ _ xử lý (và $ @, quá, ra khỏi lịch sự) trước khi eval, bạn im lặng các lỗi mà không có bộ mô tả tập tin mô tả. – pilcrow