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

Hi everyone,

Can anyone help me understand what happens here:

version 1:

map { die "bug before!" if (!defined($_)); } values %{$self->{docs}}; my @docsObservs = map { $_->getObservations() } values %{$self->{docs} +}; map { die "bug after!" if (!defined($_)); } values %{$self->{docs}}; print "ok\n";

result:

bug after! at .....

Version 2:

map { die "bug before!" if (!defined($_)); } values %{$self->{docs}}; my @docsObservs; foreach my $docP (values %{$self->{docs}}) { push(@docsObservs, $docP->getObservations()); } map { die "bug after!" if (!defined($_)); } values %{$self->{docs}}; print "ok\n";

result:

ok

This is just one part of a quite big program that I'm in the process of debugging, so I certainly still have bugs. But I'm puzzled by the fact that switching from version 1 to version 2 (without any other change) solves the issue. I can happily use version 2 of course, but I can't see what is wrong in the first version and I don't like that ;) Any idea?

Thanks!

Replies are listed 'Best First'.
Re: Strange bug with map
by Anonymous Monk on Feb 11, 2016 at 00:01 UTC

    That isn't a bug with map, it might be a bug with getObservations, maybe it assigns undef to  $_[0] or $_ which will affect the values

      Good point.

      Most likely, the "sub getObservations{}" modifies $_ , which would upset the values in the "map" case, where he uses "$_->getObservations() ".

      In the "for" loop, he uses "$docP->" as the alias for the values, so modifying $_ inside "sub getObservations" will not change the values.

      The fix would be to "local $_" inside "sub getObservations{}" where necessary.

              "Think of how stupid the average person is, and realize half of them are stupider than that." - George Carlin

Re: Strange bug with map
by erwan (Sexton) on Feb 11, 2016 at 16:04 UTC

    Thank you both for your answers. I didn't realize that $_ was not local, that explains it indeed.

    But now I have a follow up question: I don't understand why the values in the hash are affected? In my mind I assumed that $_ receives a copy of the ref to the object, so I didn't expect that when $_ is set to undef the values in the hash become undefined as well. Here is an example of what I mean:

    my @docsObservs; foreach my $docP (values %{$self->{docs}}) { push(@docsObservs, $docP->getObservations()); die "loop variable is undef after call to getObservations()" if (!de +fined($docP)); $docP = undef; } map { die "bug after!" if (!defined($_)); } values %{$self->{docs}};
    It turns out that this version dies with the "bug after" error. Is this somehow related to how the values function works? It looks as if $docP is some kind of "hard link" to the object, and not a simple copy of the ref.
      This behaviour is documented in values:

      > Note that the values are not copied, which means modifying them will modify the contents of the hash.

      It's convenient, you can do things like

      $_ = lc for values %hash;

      Note that keys don't work this way.

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

        Sorry I didn't see your answer before finding it by myself. ok now I see the point, thank you

      ok sorry, I should have read the documentation before asking:

      "Note that the values are not copied, which means modifying them will modify the contents of the hash" http://perldoc.perl.org/functions/values.html

      I find this a bit counter-intuitive actually, but that answers my question clearly.