in reply to Reference to return value of a subroutine

Your example code takes a reference to each individual list element returned by foo(), and then retains the last one.

If you want a reference to an array, you have two choices. First, you could modify the subroutine to return a reference to an array:

sub foo { return [0,1]; } my $aref = foo();

Second, you could instantiate an array reference upon receiving the return value of the subroutine:

sub foo { return (0,1); } my $aref = [foo()];

In the second example, the [...] square brackets are creating a reference to an anonymous array that is being populated by the list returned from foo().

For large lists, the first example could be more efficient since it passes a single value (the array reference) back from the subroutine call, rather than a potentially large list which must then be pulled into a new reference. We all love to hate wantarray, but how about this?

sub foo { my @rv = (0,1); return wantarray() ? @rv : \@rv; } my $aref = [foo()]; # wantarray() will be true, so the entire list ge +ts passed back and then the square braces create and populate an arra +y ref. my $aref2 = foo(); # wantarray() will be false, so inside the subrou +tine we return a reference to the array.

Yeah.... that code kind of smells because it has a strong potential of surprising the caller. Just a thought, but you'll probably want the first or second example and just keep the third as an example of something that Perl can do but maybe shouldn't. ;)


Dave

Replies are listed 'Best First'.
Re^2: Reference to return value of a subroutine
by shmem (Chancellor) on Apr 03, 2017 at 07:51 UTC
    We all love to hate wantarray

    This is flat out wrong. I for one don't. wantarray is probably the most perlish of all functions, since it is the most linguistic one. It gives elements (subroutines) which are ambiguous the ability to reveal their meaning depending on context. Bank of England, river bank, mining bank (this is itself ambiguous), bank of a billard table, battery bank, road bank - in all elements of this comma separated list the word 'bank' chooses its appropriate meaning out of all possibilities depending on its context.

    It is the only function which makes perl's ambiguity and context awareness useful for the programmer. Without a way to determine the calling context inside a sub, all the context sensivity of perl would be just a nuisance, and we would do better without it. So, wantarray is at the core of one of perl's most fundamental concepts.

    If I hated the core of perl, I'd probably program python.

    Yeah.... that code kind of smells because it has a strong potential of surprising the caller.

    Why? Does localtime smell, because it may be surprising for the caller? And then - what is more surprising for someone: a) getting the last element of the returned list, in scalar context, or b) getting a scalar reference to an array holding the elements of the returned list?

    It is all a matter of taste, convention and documentation, e.g. this

    foo() - this function returns a list of bars. When called in scalar context, you get the last element by default.
    If you want some other element, index the returned list, e.g. $thisbar = (foo($blorf))[2];

    or this

    foo() - this function returns a list of bars. If called in scalar context, it returns a reference to an array holding that list.

    Quick, which one is more intuitive for the unaware?

    So no, there is no smell here, except for those who are ashamed of some aspects of perl which are its core features and rather would weed out all ambiguities and clamp it all under the harness of e.g. PerlCritic.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'