Given
# package main;
our $f;
sub f{}
sub g {}
1;
How can I determine that $f
, but not $g
, has been declared? Off the cuff, I'd thought that *{main::g}{SCALAR}
might be undefined, but it is a bona fide SCALAR ref.
Background: I'd like to import a variable into main::
, but carp or croak if that variable is already declared.
EDIT Added an f
subroutine in response to @DVK's initial answer.
ANSWER (2010-07-27)
This isn't easy, but it is possible.
An eval
technique is most portable, working on perls older than 5.10. In more recent perls, introspective modules like Devel::Peek
and B
can discriminate.
Older perls (pre-5.10) will always have something in the scalar slot.
On newer perls, it appears that the old behavior is mimicked when you try to do *FOO{SCALAR}.
You can use the B introspection module to check the scalar slot, though:
Devel::Peek appears to be able to distinguish between used and unused things in the SCALAR slot:
The output is:
The lines of interest are under the
GP =
section, specifically SV, AV, HV, and CV (scalar, array, hash, and code, respectively). Note that the dump of*g
showsSV = 0x0
. Unfortunately, there doesn't appear to be a programmatic way to get this information. A blunt instrument approach would be to capture the output ofDump()
and parse it.You can check for a defined subroutine like so:
Unfortunately the same method only works on package variable if a value has been assigned:
/I3az/
SUMMARY
At this point, after fairly extensive research, I am of a firm opinion that in a situation when a symbol table entry with the name "X" was declared but not assigned to, it is impossible to generically distinguish which of the reference types in a glob was actually declared witout using deep probing of Devel:: stuff.
In other words, you can tell only the following 2 distinct situations:
X was not declared at all (symbol table entry does not exist)
X was declared and some of the glob types were actually assigned to.
In this second case,
You can find WHICH of the glob types were assigned to and which were not
BUT, you can not figure out which of the non-assigned-to glob types were declared-and-unassigned vs. which were not declared at all.
In other words, for
our $f = 1; our @f;
; we can tell that$main::f
is a scalar; but we can NOT tell whether@f
and%f
were declared or not - it is not distinguishable at all fromour $f = 1; our %f;
.Please note that the subroutine definitions follow this second rule as well, but declaring a named sub automatically assigns it a value (the code block), so you can never have a sub name in a "declared but not assigned to" state (caveat: might not be true for prototypes??? no clue).
ORIGINAL ANSWER
Well, very limited (and IMHO somewhat fragile) solution to distinguishing a scalar from a subroutine could be to use UNIVERSAL::can:
Result:
Please note that
{SCALAR}
does not seem to work to weed out non-scalars in my testing - it happily passed through@A
and%H
if I declared them and added to the loop.UPDATE
I tried brian d foy's approach from Chapter 8 of "Mastering perl" and somehow was unable to get it to work for scalars, hashes or arrays; but as noted below by draegtun it works for subroutines or for variables that were assigned to already:
I gave it my best, even going so far as trying to ask
eval STRING
whether$main::f
had been declared viaour
ormy
. (This required duping, closing, and later restoringSTDERR
to cut down on the chattiness.) Once you've changed packages, those declarations no longer seem visible on a temporary switchback.The technique below will detect whether
$f
has been declared viaCode below: