in reply to Determining the fully qualified name of a global variable.
This clueless newbie seeks com[m]ents on/improvements to Xyzzy.pm.
Well, OK, since you asked... ;-)
End every module with an explicit 1; to return a true value.
Closures are great, but why complicate the code when you don’t need to? In this case, named subroutines do the same job.
return undef; is redundant. From return:
If no EXPR is given, returns an empty list in list context, the undefined value in scalar context, and (of course) nothing at all in void context.
Likewise in this construct:
eval { my $obj = B::svref_2object(shift); $obj->GV->STASH->NAME . "::" . $obj->GV->NAME; } || undef;
The block form of eval is used to trap exceptions, and “the value returned is the value of the last expression evaluated inside the mini-program” but “If there is a syntax error or runtime error, or a die statement is executed, eval returns undef in scalar context or an empty list in list context”. So the || undef is redundant here.
unless ... else ... is an unnecessary double negative. Just swap the blocks and the logic becomes clear.
Here is my version of module Xyzzy.pm:
package Xyzzy; use strict; use warnings; use B; use B::Deparse; use Carp; use Devel::FindRef; use Devel::Symdump; use Exporter; our @ISA = qw( Exporter ); our @EXPORT_OK = qw( FullyQualify ); sub FullyQualify { my ($global) = @_; my @return; if (ref $global) { if (ref $global eq 'CODE') { # $ref is a ref to an autovivified sub if (B::Deparse->new->coderef2text($global) eq ';') { Carp::cluck 'FullyQualifySubName was passed a coderef +' . 'to a sub that has been autovivified!'; } else { push @return, code_ref($global); } } elsif ((ref $global) =~ m[ ^ (?: ARRAY | HASH | SCALAR ) $ ]x) { push @return, var_ref($global); } else { push @return, 'Your ref is a \'' . join(' ', @{ [ ref $global ] }) . ' ref\'!' +; } } else # ! ref $global { my $module; if ($global =~ m[^(.+)::]) # already qualified { $module = Devel::Symdump->new($1); } else # in this caller { my $caller = (caller)[0]; $module = Devel::Symdump->new($caller); $global = $caller . '::' . $global; } push @return, code_ref(eval '\&' . $global) if grep { m[ ^ $global $ ]x } $module->functions(); push @return, var_ref (eval '\%' . $global) if grep { m[ ^ $global $ ]x } $module->hashes(); push @return, var_ref (eval '\@' . $global) if grep { m[ ^ $global $ ]x } $module->arrays(); push @return, var_ref (eval '\$' . $global) . (@return ? '?' : + '') if grep { m[ ^ $global $ ]x } $module->scalars(); } return @return; } sub code_ref { my ($ref) = @_; return eval { my $obj = B::svref_2object($ref); $obj->GV->STASH->NAME . '::' . $obj->GV->NAME; }; } sub var_ref { my ($ref) = @_; my @globals = grep { $_->[0] =~ m[^the global] } Devel::FindRef:: +find($ref); return $globals[0]->[0] =~ s[^the global ][]r; } 1;
Note that I have consolidated the 5 return statements into a single return at the end of sub FullyQualify. Not necessarily an improvement (although I am a big fan of structured programming), but in this case I think it makes the code easier to follow.
Hope that helps,
| Athanasius <°(((>< contra mundum | Iustus alius egestas vitae, eros Piratica, |
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Determining the fully qualified name of a global variable. ('return undef')
by LanX (Saint) on Jan 27, 2013 at 09:28 UTC | |
|
Re^2: Determining the fully qualified name of a global variable.
by Anonymous Monk on Jan 27, 2013 at 09:01 UTC |