Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

most appropriate return data type

by Anonymous Monk
on Feb 19, 2010 at 15:29 UTC ( [id://824184]=perlquestion: print w/replies, xml ) Need Help??

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

I have a function that will return numbers. Sometimes it returns only one number; other times it returns a list of numbers.

So I was thinking that it would be best to always return an array for consistency. The array would contain only one element (when there's only one number) or multiple elements when there are more.

That way, users will always expect an array as a return value. What do you think?

Replies are listed 'Best First'.
Re: most appropriate return data type
by almut (Canon) on Feb 19, 2010 at 15:44 UTC

    There's generally nothing wrong with doing it that way (as long as you document your API clearly).

    Note that there's also wantarray, which you could use additionally to return different things depending on the calling context:

    #!/usr/bin/perl -l sub test { return wantarray ? @_ : $_[0]; } my @arr = test(1); print "@arr"; @arr = test(1,2,3); print "@arr"; my $scalar = test(1,2,3); print $scalar; __END__ 1 1 2 3 1
Re: most appropriate return data type
by cdarke (Prior) on Feb 19, 2010 at 15:47 UTC
    Which is it, an array or a list?
    use warnings; use strict; sub mysub1 { my @fred = qw(The quick brown fox); return @fred; } sub mysub2 { return qw(The quick brown fox); } my $x = mysub1(); print "x: $x\n"; my $y = mysub2(); print "y: $y\n";
    Gives:
    x: 4 y: fox
    You could always use wantarray to return a list or a scalar, depending on the context.
      Why does $y hold 'fox'? I know that mysub2() returns a list, but I don't know why $y gets assigned to 'fox'.

        The caller forces context on the return. The return value is the result of the evaluation (in the context of the caller) of the last expression in a subroutine (or the expression given to return).

        So..

        • an array in scalar context is the number of items in it.
        • in scalar context the expression ('a','b','c') isn't a list, it's a chain of comma operations:
          In scalar context, the comma operator throws away it's left operand and evaluates the right operand. So the result is c
        • the qw// operator is the comma operator in disguise

        See perlop. Ah, and 'fox' gets assigned to '$y' </nitpick> ;-)

        I can't improve on shmem's reply, but that is exactly the reason why you should be clear as to which type you intend to return - and also why you might wish to use wantarray to check for scalar context.
Re: most appropriate return data type
by pileofrogs (Priest) on Feb 19, 2010 at 18:13 UTC

    I think wantarray isn't really what the OP wants. He/She wants to know the best way to deal with a function that may return 0, 1 or more answers. Wantarray is helpful for those times when you know you only want one value. I think the OP has a situation where there is usually only 0 or 1 answer, but sometimes more than 1.

    For example, if I'm writing a function that returns the name of the hat I'm wearing. The answer is either a name or no name. Suddenly, I realise I sometimes wear more than one hat! Sometimes I wear a lot of hats! How should I write my function? Should I return a scalar when I have zero or one hat, or should I return a list even when I have one or no hats?

    The choices are generally to either check what you get from the function or always use a list/array. I generally* agree that it's best to always return a list (or list ref). If you're going to write the stuff to handle a list anyway, you're just adding extra work by writing special stuff to handle scalars. It's also more robust and it scales better. By scales better, I mean, in that one instance where you always get a scalar, you suddenly realise you want a list and you have to rewite a ton of stuff with lots of trickling expectations. Lastly, if you do decide in some special case that you want to deal with a single value differently, it's easy.

    Maybe I'm totally wrong about what the OP means though...

    * generally folks, I said generally!

    --Pileofrogs

Re: most appropriate return data type
by Xiong (Hermit) on Feb 20, 2010 at 14:18 UTC

    You haven't given enough information to get a specific answer. Why does your function return one number sometimes, more than one other times? What kind of numbers are you generating? How will the return value(s) be used? What are the consequences if some return values are ignored?

    I might write a function that returned possible lunch items available for me to eat. If, from the kinds of food in the cupboard, I had more than one possible lunch I might want to return them all. That is, given bread, peanut_butter, jam, bologna, and cheese all in stock, I might return a list of ( 'peanut butter and jelly sandwich', 'meat and cheese sandwich' ). If I call this function in scalar context, I probably will accept any of the available choices, so I should just go ahead and return the list. My scalar caller will get the last available choice.

    Or, I might write a function that returns exceptions from some process. The process might succeed or return one or more exception objects, each of which my caller must deal with in some way. I need to use wantarray to be sure my caller has Read The Fine POD; if not, I'm going to die(), which will probably get his attention and encourage him not try to call me in scalar context (thinking there can only be one exception) at all.

    Or, my function might return floating-point values from some instrumentation. Normally, only one reading will be returned on any fetch but perhaps I don't want to lose any, so I accumulate readings in some clever way. I should be called in scalar context, for efficiency, since the calls will come fast and frequently. But if I have more than one reading available, I'll return the (cardinal) number of available readings. My caller will notice the integer return and re-call in list context. Here I'll use wantarray to serve the quantity in scalar context and, in list context, to discover that he's taking the backlog off, so I'll clear my buffer.

    As usual, the intended purpose of your solution is key to determining the right approach to your code.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2024-04-24 07:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found