tags:

views:

156

answers:

3

Hey. In Python I can do this:

def fnuh():
    a = "foo"
    b = "bar"
    return a,b

Can I return a list in a similarly elegant way in perl, especially when the return type of the subroutine should be a reference to an array?

I know I can do

sub fnuh {
    my $a = "foo";
    my $b = "bar";
    my $return = [];
    push (@{$return}, $a);
    push (@{$return}, $b);
    return $return;
}

But I bet there is a better way to do that in Perl. Do you know it?

+7  A: 

Sure, just slap a \ in front of the list to return a reference.

Or make a new arrayref with [ list elements ].

In your example,

sub f1 {
    my $a = "foo";
    my $b = "bar";
    return [ $a, $b ];
}

sub f2 {
    my $a = "foo";
    my $b = "bar";
    push @return, $a, $b;
    return \@return;
}

Please see perldoc perlreftut and perldoc perlref for more about references. There is also a data structures cookbook at perldoc perldsc.

You may also want to read this question in the perlfaq (thanks brian): "What's the difference between a list and an array?"

Ether
The second way you definitely want to declare `@return` with `my`, otherwise it becomes global which is not so good.
Dan
"# the last expression is returned automatically; no need to be explicit" - regarding this, I like python better. From "the zen of python", second statement: Explicit is better than implicit.So I would prefer: return [$a, $b];
0x89
I prefer to always do explicit returns. There's nothing wrong with adding a bit of clarity. Especially in Perl. :)
friedo
The thing python fans fail to realize is that the Zen of Python is load of crap. Imagine reading a sentence if you had to be explicit and encode what each part of the sentence the word was and where it was positionally located. FIN := (noun,statement;terminating word)
Evan Carroll
Perl Best Practices, Chapter 9, Item: Implicit Returns: "Always return via an explicit return". I don't think that Damian Conway prefers Python, but he is on my side here.
0x89
I didn't mean to offer an opinion as to whether implicit returns are okay. :) It's just that in my initial edit I left off the `return`, so I went back in and added a comment just to point out the possibility, in case anyone was not aware of this property in Perl. FWIW, I always use an explicit return if I care about the return value, and leave it off if I am more interested in the function's side effects.
Ether
I suggest that f1 should end `return [ $a, $b ];` instead of `my $return = [ $a, $b ];`. The way you've written it says to me, at least, that you're not done with that function yet. Why else bind it to a lexical?
derobert
@0x89: Damian being on your side doesn't mean much than some other people being on your side. He's not someone he intends you to worship. See my interview with him for how you should approach PBP: http://www.theperlreview.com/Interviews/damian-bpp-20050622.html
brian d foy
@derobert: I was simply copying the OP's function template as nearly as possible, while demonstrating how to use references. (PS. You guys are overanalyzing WAY too much here. The original question was about arrayrefs, remember?)
Ether
+6  A: 

Python automatically packs and unpacks tuples around an assignment simulating lists. In Perl, you can write it the same way, returning a list.

sub fnuh {
    my $a = 'foo';
    my $b = 'bar';
    $a, $b
}

then to use the result:

my ($x, $y) = fnuh;

or if you need the reference:

my $ref = [ fnuh ];
Eric Strom
I like the simplicity of this answer. Also, `wantarray`.
Leonardo Herrera
some more pedantry: Perl Best Practices, Chapter 2: Code Layout, Semicolons: "Place a semicolon after every statement".Chapter 4: Values and Expressions, Lists: "Parenthesize every raw list".The minimalist in me likes the terse syntax, though.
0x89
Perl Best Practices isn't the Holy Bible. It's what Damian likes to do. It doesn't mean that you have to do it. See my interview with him: http://www.theperlreview.com/Interviews/damian-bpp-20050622.html
brian d foy
I prefer to explicitly leave the semicolon off the last line when not using the `return` keyword. That way, if any code is ever placed after that line it will likely be a syntax error. It also reinforces the fact that without a return, subs return their last statement. I find that many of the guidelines in PBP are defensive techniques that call back to a day before decent real time syntax checking.
Eric Strom
A: 

You can get the same function as Python by explicitly testing whether the context wants an array with the function wantarray.

sub fnuh {
    my $a = 'foo';
    my $b = 'bar';
    return wantarray ? ( $a, $b ), [ $a, $b ];
}

Or if you want to do this a lot, you could write a function that will be able to read the same context, as long as you have not altered it.

sub pack_list { 
    my $want = wantarray; 
    return unless defined $want; # void context
    return $want ? @_ : \@_;
}

Then call it like this:

return pack_list( $a, $b );
Axeman
Dealing with contexts in Perl is best way to shoot yourself to foot.
Hynek -Pichi- Vychodil
@ Hynek -Pichi- Vychodil: I'm not sure why you say that. *Context* is one of the things I like best in Perl. When I work in Java, I often wish I could do the same thing without extra parameter passing and overloading. *If* you're not familiar with context, it can be confusing.
Axeman