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

Sorry for the lousy title, but I couldn't express it better.

Why does this produce different output and a warning...

use List::Util qw[ reduce ]; print reduce{ eval "$a + $b" } 1,2,3; Use of uninitialized value in concatenation (.) or string at ... 3

To this?

use List::Util qw[ reduce ]; print reduce{ my $n = eval "$a + $b" } 1,2,3; 6

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.

Replies are listed 'Best First'.
Re: An anomaly with List::Util::reduce and/or eval?
by liz (Monsignor) on Aug 12, 2003 at 19:12 UTC
    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.

      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

        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

Re: An anomaly with List::Util::reduce and/or eval?
by sgifford (Prior) on Aug 12, 2003 at 19:36 UTC
    I don't get this error with my own implementation of reduce:
    #!/usr/bin/perl -w use vars qw($a $b); sub myreduce(&@) { my $sub = shift; $a = shift; foreach $b (@_) { $a = $sub->(); } $a; } print myreduce{ eval "$a + $b" } 1,2,3;
Re: An anomaly with List::Util::reduce and/or eval?
by runrig (Abbot) on Aug 12, 2003 at 19:11 UTC
    What version of perl and List::Util? With perl 5.6.1 and List::Util 1.09, that first version gives me a segfault. I know that List::Util has had stack issues in the past when you do anything non-trivial in the code block, I don't know if that has anything to do with it.

    Update: Just updated to List::Util 1.11 - Same result.

      Sorry. Should have included that info.

      P:\test>perl -MList::Util -le"print $List::Util::VERSION" 1.07 P:\test>perl -v This is perl, v5.8.0 built for MSWin32-x86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2002, Larry Wall Binary build 802 provided by ActiveState Corp. http://www.ActiveState. +com Built 00:54:02 Nov 8 2002

      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.

Re: An anomaly with List::Util::reduce and/or eval? (XS)
by tye (Sage) on Aug 12, 2003 at 23:23 UTC

    This is just the type of thing that has lead me to dislike enthusiastic optimization as well as most XS modules. I'd rather something like 'reduce' be written in Perl.</soapbox> (:

                    - tye

      Well, you do have that choice. Delete the dll or unix equivalent and the code falls back to a pure perl version.

      Mind you, there is no guarentee that the perl version will be bug-free.

      Nor is there any evidence that shows this to be a bug that results from an optimisation, unless you consider writing anything in XS an optimisation? In which case maybe we should revert to a pure perl implementation of sort, map etc.?

      I mean. Last week I found a bug in substr. Was that also a csae of "over-optimisation"?


      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.

        anything in XS an optimisation? In which case maybe we should revert to a pure perl implementation of sort, map etc.?

        Are you trying to assert that sort and map are implemented via XS? My objection is about XS code, not that the Perl source code is written in C.1

        Mind you, there is no guarentee that the perl version will be bug-free.

        There are few true guarantees in life. I'm not sure why you felt I was trying to offer one or assert the existence of one. But I'd be happy to bet you that this bug will go away if you follow your own instructions on how to remove the XS code. My assertion is that XS code is more likely to be buggy than Perl code. Actually, I find it to be far more likely to be buggy.

        Nor is there any evidence that shows this to be a bug that results from an optimisation, unless you consider writing anything in XS an optimisation?

        No, I don't consider writing anything in XS to be an optimization. But you tell me, why would one have the same functionality written in both Perl and XS? Why is the XS code present in this case? I'm pretty sure the primary (probably only) reason for this XS code is an attempt to increase "performance".

        Examine what is said.

                        - tye

        1Perhaps you would like to implement "reduce" as a Perl keyword and then compare the resulting code to the current XS code in order to appreciate that the two ways of implementing Perl functionality in C are quite different. Then try to get your code included into Perl and compare that to getting your XS code into CPAN.

Re: An anomaly with List::Util::reduce and/or eval?
by sgifford (Prior) on Aug 12, 2003 at 19:14 UTC
    I get the same results as you for the second (although with warnings), but more drastic ones for the first!
    Name "main::a" used only once: possible typo at /tmp/t76 line 5.
    Name "main::b" used only once: possible typo at /tmp/t76 line 5.
    semi-panic: attempt to dup freed string at /tmp/t76 line 5.
    Segmentation fault (core dumped)
    

    This is with Perl 5.6.1, and List::Utils 1.11.

      Thanks for the confirmation. As I belatedly posted, I'm on 5.8 and 1.07... I'll try pullling a later version of List::Util (if I can get it to build).


      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.

Re: An anomaly with List::Util::reduce and/or eval?
by demerphq (Chancellor) on Aug 13, 2003 at 16:42 UTC

    I dont experience your bug. It must have appeared sometime after AS 633....

    #!perl -l use List::Util qw[ reduce ]; print "\$List::Util::VERSION = $List::Util::VERSION\n"; printf "Perl version: %vi\n",$^V; print reduce{ print "$a $b"; eval "$a + $b" } 1,2,3; print reduce{ eval "$a + $b" } 1,2,3; __END__ $List::Util::VERSION = 1.07 Perl version: 5.6.1 1 2 3 3 6 6
    This is perl, v5.6.1 built for MSWin32-x86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2001, Larry Wall Binary build 633 provided by ActiveState Corp. http://www.ActiveState. +com Built 21:33:05 Jun 17 2002

    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

      Do you have the compiled version of List::Util installed? Ie. Do you have lib/auto/List/Util/Util.dll?

      If the compiled version isn't available, then the module falls back to using pure perl code. Maybe that is the difference?


      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.

        Yep. You're right. I have the XS one at home. I get the same problem now that I've compiled it properly.

        Incidentally theres been a few things on p5p that you might want to follow. Apparent 5.8.1 RC5 wont come with the perl implementation?!


        ---
        demerphq

        <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
Re: An anomaly with List::Util::reduce and/or eval?
by demerphq (Chancellor) on Aug 13, 2003 at 22:01 UTC

    In case you havent seen there was a patch posted to p5p. I tried it out and it resolves the problem.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...