Ah, I know where you're coming from. When I was new to Perl, I was trying to write exactly such a thing. Just like you I found lexical scoping to be a show-stopper. Years later I learned about a way around that and wrote a utility module Report.pm, exporting report() which works much like your proposed display_init(), except that it doesn't prepend a "$" to the given items.

Fact of the matter is that I never use it. Inserting normal print/warn/die statements just comes more natural after all this time. The code is essentially the first version that ran, I never bothered to clean it up. Anyway, here it is:

The core module DB has the property that eval(), when called from DB, runs in the lexical context of its caller. That can be used to report values of expressions involving lexical variables in the caller's context. Report.pm exploits that. It is used like this:
use Report 'report'; my ( $i, $j) = ( 42, 'freeBSD'); my %h = ( one => [ 4, 5, 6], two => 'gaga'); report qw( $i $j $h{one} $h{two} $h{three});
That prints
$i = 42; $j = 'freeBSD'; $h{one} = [ 4, 5, 6 ]; $h{two} = 'gaga'; $h{three} = undef;
Here is the module Report.pm
package Report; use strict; use warnings; # @^~` use base 'Exporter'; our @EXPORT = qw( report); { # DB evaluates in caller context package DB; sub DB::_report_report { for my $expr ( @_ ) { print Report::answer( $expr, eval $expr); } } } *Report::report = \ &DB::_report_report; use Data::Dumper (); use Scalar::Util (); sub answer { my ( $expr, @val) = @_; my $ans; if ( $@ ) { $ans = "$expr: $@" if $@; $ans =~ s/ at \(eval .*$//; } else { if ( @val == 1 ) { $ans = answer_scalar( $expr, @val); } else { $ans =join ', ' => map answer_scalar( $expr, $_), @val; $ans = "($ans)"; } } $ans; } sub answer_scalar { my ( $expr, $val) = @_; my $ans; if ( !defined $val ) { $ans = "$expr = undef;\n"; } elsif ( ref $val ) { ( $ans = Data::Dumper::Dumper $val) =~ s/\$VAR1\b/$expr/g; my $indent = ' ' x ( 8 + length( $expr) - length( '$VAR')); $ans =~ s/^ {8}/$indent/mg; } elsif ( Scalar::Util::looks_like_number( $val) or ref( \ $val) eq 'GLOB' ) { $ans = "$expr = $val;\n"; } else { $ans = "$expr = '$val';\n"; } $ans; } 1;
Anno

In reply to Re: issues with eval (get a variable's value) by Anno
in thread issues with eval (get a variable's value) by squale

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.