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

Suppose you have a subroutine which returns an array ref. There are basically two ways to do it:
sub first_way { my @list; ... add elements to @list... \@list; } sub second_way { my @list; ... add elements to @list... [ @list ]; }
Is there any significant differences between the two in terms of performance or memory usage?

Are there any potentially adverse consequences of holding on to references to static lexical variables?

Update: replaced static with lexical

Replies are listed 'Best First'.
Re: returning ref to static var vs. copying
by JavaFan (Canon) on Jun 09, 2009 at 23:41 UTC
    Is there any significant differences between the two in terms of performance or memory usage?

    If @list is big, yes. The latter makes a copy, which takes time, and uses about twice the amount of memory, half of which is available for reuse since @list goes out of scope.

    Are there any potentially adverse consequences of holding on to references to static variables?
    The closest thing Perl has to static variable are "state" variables (new in 5.10). Your codes doesn't have any.

    Returning references may have the danger that something else is also holding some reference to it. And he who has the reference has the power to modify it. If there's nothing else holding a reference, there's little danger.

      I guess I meant to say lexical instead of static.
      If @list is big, yes. ...
      One thing I was wondering was if perl can optimize this case and not perform the copy.
        Determining whether something is big is easy. But returning a reference is something else that returning a copy. One could determine in a limited amount of cases whether returning a reference instead of a copy isn't hurtful (but not in general, as that will involve solving the halting problem), but
        1. Determining something like that takes time. Which means that each such case slows down. Even if in the end the conclusion is that the copy needs to be done after all.
        2. The gain for the programmer would be minimal. It's not that [@list] is shorter to write than \@list.
        3. Noone has written such a patch.
        Given 1) and 2), even if someone did 3) I wouldn't bet on it it gets accepted.
Re: returning ref to static var vs. copying
by shmem (Chancellor) on Jun 10, 2009 at 00:06 UTC
    The construct [ @list ] creates a new array reference, into which @list is expanded (i.e. copied), so that's bloat.

    Are there any potentially adverse consequences of holding on to references to static variables?

    No, since the my @list isn't static. That container will be empty at each subroutine invocation, and it's contents will live in a brand new reference which you can take with \@list...

    use strict; use warnings; sub foo { my @list if 0; print "list: (@list)\n"; push @list, @_; \@list; } my $ref1 = foo(1..3); push @$ref1, 'a', 'b'; my $ref2 = foo(4..6); print "first ref: (@$ref1)\n"; print "last list: (@$ref2)\n"; __END__ list: () list: () first ref: (1 2 3 a b) final list: (4 5 6)

    ...except if you play tricks to the compiler (allocate a private @list on the scratchpad, but don't generate the opcode to clear that list) like so:

    use strict; use warnings; sub foo { my @list if 0; print "list: (@list)\n"; push @list, @_; \@list; } my $ref1 = foo(1..3); push @$ref1, 'a', 'b'; my $ref2 = foo(4..6); print "first ref: (@$ref1)\n"; print "final list: (@$ref2)\n"; __END__ list: () list: (1 2 3 a b) first ref: (1 2 3 a b 4 5 6) last list: (1 2 3 a b 4 5 6)

    But that's deprecated. For statics (previous perl 5.10) you'd use a block around the sub

    use strict; use warnings; { my @list; sub foo { print "list: (@list)\n"; push @list, @_; \@list; } } my $ref1 = foo(1..3); push @$ref1, 'a', 'b'; my $ref2 = foo(4..6); print "first ref: (@$ref1)\n"; print "final list: (@$ref2)\n";

    which produces the same output like the infamous 'my if 0' hack above, but you get at a glance what is going on: the @list is allocated in the same scope into which sub foo has been compiled, but @list isn't re-initialized inside the sub.

      But that's deprecated.

      It was never deprecated since it was never valid.

        The warning message Perl itself emits when it encounters this construct describes it as "deprecated". Surely it's reasonable to follow that example?

Re: returning ref to static var vs. copying
by trwww (Priest) on Jun 11, 2009 at 05:21 UTC

    uppose you have a subroutine which returns an array ref. There are basically two ways to do it:

    Theres another way. Instead of making an @array, always use an array ref:

    sub third_way { my $array_ref = []; ... add elements to $array_ref... $array_ref; }

    regards,

      It does have the advantage of consistency: The array is accessed by reference both in and out of the function.