bsb has asked for the wisdom of the Perl Monks concerning the following question:

In trying to write tests for Data::Rmap I found an oddity. I don't understand why these two should produce different results:
$ perl -MData::Rmap -e 'eval { rmap { $_++ } 1 }; print $@;' $ perl -MData::Rmap -e ' rmap { $_++ } 1 ' Modification of a read-only value attempted at -e line 1.
What could explain the difference?

I'll put the code for Data::Rmap in a follow-up, but I haven't been able to replicate the problem in simpler code (the simpler version works).

Brad

Replies are listed 'Best First'.
Re: Why no $@ after eval? Bug?
by Chady (Priest) on May 07, 2004 at 09:07 UTC

    They do not produce different results. Look:

    $ perl -e 'eval { map { $_++ } 1 };' $ perl -e 'eval { map { $_++ } 1 }; print $@;' Modification of a read-only value attempted at -e line 1. $ perl -e ' map { $_++ } 1 ' Modification of a read-only value attempted at -e line 1.

    In the first attempt, you have your code in an eval block, so the error is stored in $@.

    Now, why isn't it getting printed?
    I'm assuming it's because rmap evaluates the code it is being handed my @got = eval { $self->call(); }; so it is overwriting the value of $@ and thus when your eval block gets out it doesn't print the error message. I would assume that calling evals inside of eval could get messy.

    Someone cares to elaborate about eval inside of eval? for example, why doesn't this:

    $ perl -e '$n = q/eval { die;}; print "1: $@"/; eval {$n}; print "2: $ +@"'
    print out "1: Died at (eval 1) line 1." ?


    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady | http://chady.net/

      Someone cares to elaborate about eval inside of eval? for example, why doesn't this:

      $ perl -e '$n = q/eval { die;}; print "1: $@"/; eval {$n}; print "2: $ +@"'
      print out "1: Died at (eval 1) line 1." ?

      Mainly because you left out "-w", which would have helped point you to the fact that you used eval {$n} instead of eval $n. Making that change gives you the output you'd expect.

      Hugo

Re: Why no $@ after eval? Bug?
by Corion (Patriarch) on May 07, 2004 at 08:52 UTC

    Some short toying around results in these two short examples that yield no error/warning on ActiveState Perl 5.6.1 (Win32):

    1>perl -we "sub rmap(&@){1}; eval { rmap { $_++ } 1 }; print $@;" 2>perl -we "sub rmap(&@){1}; rmap { $_++ } 1"

    Replacing rmap with map yields the error you get in both cases:

    3>perl -we "eval { map { $_++ } (1) }; print $@;" Modification of a read-only value attempted at -e line 1. 4>perl -we " map { $_++ } (1) " Modification of a read-only value attempted at -e line 1.

    But I don't see why my cases 1 and 2 do not raise the error you want.

    Update: Of course, ysth is correct, but with my modified variant (5 and 6, replacing 1 and 2), I get the error in both cases, as expected

    5>perl -we "sub rmap(&@){my $c=shift;$c->($_) for @_}; rmap { $ +_++ } 1 print $@;" syntax error at -e line 1, near "1 print" Execution of -e aborted due to compilation errors. 6>perl -we "sub rmap(&@){my $c=shift;$c->($_) for @_}; rmap { $ +_++ } 1; print $@;" Modification of a read-only value attempted at -e line 1.

    So maybe your special rmap doesn't call the callback in all cases?

      Because your sub rmap doesn't actually call the coderef passed to it, so the increment is never actually done?
Re: Why no $@ after eval? Bug?
by hv (Prior) on May 07, 2004 at 11:33 UTC

    Looking at the code in your followup, I'd expect this is down to the use of local $@ just before the eval in _rmap() - if the eval fails, you die $@, which puts the error message in $@, which is then overwritten when the original $@ is restored on unwinding.

    I'd suggest it should instead do something like (untested):

    my $error; my @got; { local $@; @got = eval { $self->call(); }; if ($@) { if (ref($@) && $@ == $cut) { push @return, @$cut; next; } else { $error = $@; } } } die $error if $error; push @return, @got;

    Hugo

      That's it. Thanks
Code for: Why no $@ after eval? Bug?
by bsb (Priest) on May 07, 2004 at 08:45 UTC
    Here's the code for Data::Rmap, docs trimmed