in reply to An anomaly with List::Util::reduce and/or eval?

Just curious. is there a reason for using string eval here? Why not:
print reduce { $a + $b } 1,2,3;
Anyway, if I change it to:
print reduce{ print "a = $a, b = $b\n"; eval "$a + $b" } 1,2,3,4;
I get:
a = 1, b = 2
Use of uninitialized value in concatenation (.) or string at 1 line 4.
a = , b = 3
Use of uninitialized value in concatenation (.) or string at 1 line 4.
Use of uninitialized value in concatenation (.) or string at 1 line 4.
a = , b = 4
Use of uninitialized value in concatenation (.) or string at 1 line 4.
4
which explains the 3 that you're seeing. Apparently the eval is returning undef.

No further ideas, I'm afraid. Hmmm... maybe an optimalization that's over optimizing?

Liz

Update
Mine was with the 20581 snapshot (5.8.1-RC5 to be, List::Util 1.11)

Update:
Graham Barr wrote on p5p on August 14, 2003:

This is close, but not right as it will result in $a being modified when
the sub returns. Later today I will release 1.12 with a fix for this.
while referring to List::Util.

Replies are listed 'Best First'.
Re: Re: An anomaly with List::Util::reduce and/or eval?
by BrowserUk (Patriarch) on Aug 12, 2003 at 19:27 UTC

    I was using a string because the '+' in the example was actually a runtime supplied argument (see Re: array problems).

    I see the same errors, but I don't understand why eval would return undef.... Or maybe I do.

    I think you hit the nail on the head liz!

    <DEEP SPECULATION>Maybe eval is using wantarray to detect a void context and returning undef? But that would mean wantarray is failing to detect the body of reduce as a LIST context?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      reduce { print wantarray ? "array\n" : defined wantarray ? "scalar\n" : "void\n" } 1 .. 2; # prints "void"
      So the eval must optimize itself based on the context, but a normal non-eval'ed block ending with $a + $b would not optimize away, and (I think) still perform and return the addition, even though being in void context.

      Certainly I agree that you are right, that this must be a bug in List::Util. The block should be in scalar context since the return value is the important part of this operation. I really wonder how the module can get the return value of something that it executes in void context??

      Also, I got some strange behavoir when I add a return statement to the eval. Both should behave the same way, but don't. Why on earth $a gets set to 4 for every addition is a mystery...

      my $result = reduce { print "eval: $a + $b\n"; eval "$a + $b" } 1 .. 4; print "result=$result\n\n"; # eval: 1 + 2 # eval: + 3 # eval: + 4 # result=4 $result = reduce { print "eval: return $a + $b\n"; eval "return $a + $b" } 1 .. 4; print "result=$result\n\n"; # eval: return 1 + 2 # eval: return 4 + 3 # eval: return 4 + 4 # result=4
      Update: sgifford claims to see scalar context from the block in his reply above -- running his code, I still get void context reported.. This is with Perl 5.8, and List::Util 1.07_00. But even in scalar context, he still gets the weird behavoir? The wonders never cease!

      blokhead

        Your code prints "scalar" for me as well.

        I'm using Perl 5.6.1, List::Util 1.11.

        Very strange indeed.

      I thought the same thing, but it doesn't seem so:
      #!/usr/bin/perl -w use List::Util qw[ reduce ]; print reduce{ print "a = '$a', b = '$b'\n"; eval "showcontext($a + $b) +";} 1,2,3; sub showcontext { print "Context: "; if (wantarray) { print "array\n"; } elsif (defined(wantarray)) { print "scalar\n"; } else { print "void\n"; } $_[0]; }
      produces:
      $ perl /tmp/t76
      a = '1', b = '2'
      Context: scalar
      Use of uninitialized value in concatenation (.) or string at /tmp/t76 line 5.
      a = '', b = '3'
      Use of uninitialized value in concatenation (.) or string at /tmp/t76 line 5.
      Context: scalar
      3
      
      ...failing to detect the body of reduce as a LIST context?

      But it is in scalar context: try forcing a list contect by prefixing the eval with () = ;-)

      Liz