in reply to references best practice

Regarding the first and last alternatives (returning a plain list or an array reference): there's a middle road here that you sometimes encounter. The routine can return a list in list context and an array reference in scalar context. That is, it usually looks like this:

sub foobar { ... return wantarray ? @foobar : \@foobar; }

Let's say foo always returns a plain array, bar always returns the array reference, and foobar is the middle road. Then you'll have

| foo | bar | foobar | "best" ------+-----------+----------+-------------+------------- List | foo() | @{bar()} | foobar() | foo / foobar Ref | [ foo() ] | bar() | foobar() | bar / foobar Count | foo() | @{bar()} | @{foobar()} | foo
and in terms of memory efficiency this translates to
| foo | bar | foobar ------+-----------+----------+-------- List | copy | copy | copy Ref | copy | no-copy | no-copy Count | no-copy | no-copy | no-copy
This sums up to foobar having a more convenient syntax than bar when memory isn't an issue, yet has the same memory efficiency.

However, when dealing with large lists and you only want the count/length, you can't in foobar use wantarray to make the sometimes very useful optimization (both speed- and memory-wise) of not fully processing all elements but just return the count. (For instance, your list may contain objects that then needn't be created.)

My conclusion is, as ever so often, that it depends, and it's almost always just a convenience decision. In the worst case you just create foo_ref or bar_count.