Given a typeglob, how can I find which types are actually defined?
In my application, we user PERL as a simple configuration format. I'd like to require() the user config file, then be able to see which variables are defined, as well as what types they are.
Code: (questionable quality advisory)
#!/usr/bin/env perl
use strict;
use warnings;
my %before = %main::;
require "/path/to/my.config";
my %after = %main::;
foreach my $key (sort keys %after) {
next if exists $before{$symbol};
local *myglob = $after{$symbol};
#the SCALAR glob is always defined, so we check the value instead
if ( defined ${ *myglob{SCALAR} } ) {
my $val = ${ *myglob{SCALAR} };
print "\$$symbol = '".$val."'\n" ;
}
if ( defined *myglob{ARRAY} ) {
my @val = @{ *myglob{ARRAY} };
print "\@$symbol = ( '". join("', '", @val) . "' )\n" ;
}
if ( defined *myglob{HASH} ) {
my %val = %{ *myglob{HASH} };
print "\%$symbol = ( ";
while( my ($key, $val) = each %val ) {
print "$key=>'$val', ";
}
print ")\n" ;
}
}
my.config:
@A = ( a, b, c );
%B = ( b=>'bee' );
$C = 'see';
output:
@A = ( 'a', 'b', 'c' )
%B = ( b=>'bee', )
$C = 'see'
$_<my.config = 'my.config'
In the fully general case, you can't do what you want thanks to the following excerpt from perlref:
But if you're willing to accept the restriction that any scalar must have a defined value to be detected, then you might use code such as
will get you there.
With
my.config
ofthe output is
Printing the names takes a little work, but we can use the
Data::Dumper
module to take part of the burden. The front matter is similar:We need to dump the various slots slightly differently and in each case remove the trappings of references:
Finally, we loop over the set-difference between
%before
and%after
:Using the
my.config
from your question, the output is