in reply to How to get variable name in trace message

Perl doesn't make this sort of thing especially easy. Devel::Assert kinda pulls off this trick...

use Devel::Assert -all; my $x = 2; assert($x > 3);

The above will die with the message: Assertion ' $x > 3 ' failed at assert.pl line 5.

How does Devel::Assert do it? With a bit of Devel::Declare magic. Devel::Declare hooks into the Perl compiler, rewriting code before it gets compiled. Using Devel::Declare you could define your own Dumper function which rewrites this:

Dumper($foo)

to this:

Data::Dumper->Dump([$foo], [qw[$foo]])

Not impossible, but probably more effort than it's worth.

perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Replies are listed 'Best First'.
Re^2: How to get variable name in trace message
by tobyink (Canon) on Jun 15, 2012 at 09:08 UTC

    While I still stand by the "more effort than it's worth" comment, I've been meaning to get more stuck into Devel::Declare lately, so I had a go, and this is what I came up with:

    Data::Dumper::Declare

    It gives you a Dumper function just like Data::Dumper (in fact, it uses Data::Dumper internally, so respects things like $Data::Dumper::Sortkeys), but figures out the variable names being dumped. So you can do this:

    use Data::Dumper::Declare; my $foo = 1; my $bar = 'Hello World'; my @baz = qw(1 2 3); print Dumper($foo, substr($bar, 0, 5), @baz);

    ... and you get:

    $foo = 1;
    $EXPR = 'Hello';
    \@baz = [
      1,
      2,
      3
    ];
    

    (Note that unlike Data::Dumper, you can't just eval the output. An assignment like \@bar = [...] is illegal.)

    Data::Dumper::Declare isn't on CPAN yet. Do people think it useful enough to upload?

    Update: just pushed a change which allows arrays and hashes to be dumped more nicely. e.g.

    @baz = (
      1,
      2,
      3
    );
    

    Update 2: Data::Dumper::Declare is now on CPAN.

    Update 3: Given this:

    use Data::Dumper::Declare; my @foo = qw(Hello World); print Dumper( @foo, $foo[0], $foo[1], join('::', @foo), );

    The output is:

    @foo = (
      'Hello',
      'World'
    );
    $foo[0] = 'Hello';
    $foo[1] = 'World';
    $EXPR = 'Hello::World';
    

    Can anyone suggest something better than $EXPR in the output? It's certainly possible to output join('::', @foo) = 'Hello::World'; but I'm not especially fond of that. What do other people think?

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Data::Dumper::Declare isn't on CPAN yet. Do people think it useful enough to upload?
      Definitely! This is something I always wanted to have!!!

      -- 
      Ronald Fischer <ynnor@mm.st>

      There is no variable name associated with the expression, so undef could work, and it is ok to assign to undef.

      Quoting the expression might also be a nice option if possible.

      $foo = 1; undef = 'StringResultOfExpression'; $str . result('expression') = 'StringResultOfExpression'; @bar = [ 1, 2, 3, ];
      That's great - you've put a lot of work into it. Personally, I do like the explicit join('::', @foo) in the output.
Re^2: How to get variable name in trace message
by ChrisBeall (Novice) on Jun 15, 2012 at 06:15 UTC
    You guys are amazing! Thanks for such a thoughtful response. I'll have a play around with Devel::Declare.