Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

More efficient dereferencing of a subroutine return

by gg48gg (Sexton)
on Feb 17, 2013 at 22:46 UTC ( [id://1019227]=perlquestion: print w/replies, xml ) Need Help??

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

I am inquiring to see if there is a more efficient way, than the below code, to dereference a reference returned from a subroutine. Could you please help me out?

my $temp_scalar=subroutine(); my @ARRAY=@$temp_scalar; undef $temp_scalar; sub subroutine { my @array=("one", "two"," three"); return \@array; }

Replies are listed 'Best First'.
Re: More efficient dereferencing of a subroutine return
by tobyink (Canon) on Feb 17, 2013 at 22:54 UTC
    my @ARRAY = @{ subroutine() };

    This is fewer lines of course, and arguably a bit neater than a temporary variable, but in terms of real efficiency (i.e. CPU, memory, etc) makes very little difference.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      Darn thing causes fatal error of Can't use an undefined value as an ARRAY reference if undef is received under strict 'refs', where the dereference result could have been an empty list without the need to invoke no strict .... I will take the temporary variable to do a check first.
        Can you show what exactly gives you that error? I get no errors/warnings with this:
        #!/usr/bin/env perl use strict; use warnings; use feature 'say'; my @result = @{ subroutine() }; say "@result"; sub subroutine { my @array = (); return \@array; }

        In that case,

        my @ARRAY = @{ subroutine() || [] };
        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
        what? Can you demonstrate that?

      If the dereferencing of an array returned by a function is my $arrayref = \@{ function() } then how does that work with the keys() function?

      I tried my $arrayref = \@{ keys(%$someHashRef) || [] } but something makes it break.

      What makes the keys() function a special case?

        You say "dereferencing", but at the same time "$arrayref". That's confusing.

        To dereference an array reference returned from a subroutine, you can use:

        my @array = @{ sub_returning_aref() };

        To get the actual reference, no dereferencing is needed:

        my $aref = sub_returning_aref();

        On the other hand, if a subroutine returns a list, you can assign it directly to an array:

        my @array = sub_returning_list();

        To create an array reference, you need to create an anonymous array, as the subroutine returns a list, not an array.

        my $aref = [ sub_returning_list() ];

        There's nothing special about keys.

        my @array = keys %hash; my $aref = [ keys %hash ];

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Thanks to everyone for your input. For my purposes, I don't have to worry about the possibility of my sub returning undef. So, I like tobyink's:

      my @ARRAY = @{ subroutine() };
      for it's simplicity and function. I will keep in mind Anon's recommendation for using 'eval' in the event I need to handle possibility of undef. Thanks all! I hope this thread is useful for others in the future. I didn't find what I was looking for when I searched. Cheers.
        Hey all. Related question. Is there a way to avoid this multi step operation when I have multiple return values of a sub? e.g.:
        my ($ref1, $ref2) = retarrayrefs(); my @arr1=@$ref1; my @arr2=@$ref2; sub retarrayrefs { my @arr1=qw(one two three); my @arr2=qw(four five six seven); return (\@arr1,\@arr2); }
        I was trying many variations of the below, but none work properly, and it just doesn't seem like a good thing to do. Should I stop trying to shorten this code and simply stick with the above?
        my (@arr1,@arr2) = ( ${retarrays()[0]}, ${retarrays()[1]} );
Re: More efficient dereferencing of a subroutine return
by LanX (Saint) on Feb 18, 2013 at 02:40 UTC
    Are you aware that Perl has list-context?

    my @ARRAY=subroutine(); sub subroutine { my @array=("one", "two"," three"); return @array; }

    If you still need to return an array-ref in other cases just check wantarray in a condition to see if a scalar is expected.

    return wantarray ? @array : \@array;

    Cheers Rolf

Re: More efficient dereferencing of a subroutine return
by bulk88 (Priest) on Feb 18, 2013 at 02:16 UTC
    Don't make a copy of the array to another array. no "my @ARRAY=@$temp_scalar;" just do $temp_scalar->[5].

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1019227]
Approved by frozenwithjoy
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-23 23:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found