Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Before I start arguing for my case I'd like to point out that instead of writing   return wantarray ? @arr : $arr[-1]; to return the last argument in scalar context you can do   return @arr[0..$#arr]; Perhaps it's neither efficient nor clear, but I thought it could be worth mentioning.

Besides that, I don't have much against   my ($x) = foo(...); Though, consider a method like this:
sub get_headers { my $self = shift; my @headers = @_; my @values = @{$self->{headers}}{@headers}; return @values; }
I hope it's clear what it does. It could be called like   my ($recipient, $sender) = $obj->get_headers('to', 'from'); But this is a typical subroutine that you often call with one element,   my ($recipient) = $obj->get_headers('to'); thus benefit from making that last return statement honour wantarray:   return wantarray ? @values : $values[0]; and now you can do   my $recipient = $obj->get_headers('to'); and I find this quite DWIMy.

But, how much sense does   my $recipient = $obj->get_headers('to', 'from'); make? Not much, if you're asking me. For that reason, I think that it would be suitable to issue a warning if the function was called in scalar context with more than one argument.

Even if that behaviour is documented to either return the last or first element it can be confusing when maintaining code. Since the construction doesn't make much sense you have to look in the documentation again, because you've probably forgotten if it'll return the first or last element. For that reason, I don't call subroutines with arguments it doesn't make use of. I haven't yet some across a case where I've felt a special desire to pass more arguments to the function than the function will use.

It would also feel unsafe. The argument for this is pretty weak, but here it comes anyway. The author perhaps didn't think it through so well, and the current behaviour was just a consequence of the algorithm and he thought "why not, I might as well add this feature [prematurely]" (that happens a lot--that people add things prematurely, that is). And then he realizes that in scalar context the subroutine can be extra spiffy if it gets an extra argument or two. And that he can add, since it doesn't make sense to give more than one argument in scalar context anyway, right? Note that I'm not hoping that this would ever happen, but I think it can, and I'm a paranoid programmer. I'm especially paranoid against other programmers, and it does happen that module authors don't think through their API thoroughly.

The &foo routine's return behaviour Aristotle presents isn't fully comparable to my &get_headers method though. In &foo the result depends on the value rather than number of parameters. If it can't be decided by looking directly at scalar @_ then you really ought to warn if the result gets longer than one element. It quite probably wasn't intended. If not, what's the harm in forcing the programmer to in this particular case disambiguate by putting a pair of parentheses? We use disambiguation tricks all the time, like +{} in maps and such.

To sum it up as a general rule of thumb: If a subroutine has the character of returning a list, but sometimes returns just one element, then it can be made so that in scalar context it returns that very element. But if it's called in scalar context and it in list context would have returned more than one element then it should warn.

Code-wise this means
return @results if wantarray; carp("More than one value in result in scalar context") if @results > 1; return $results[0];
Just my thoughts,
ihb

In reply to Re: Context aware functions - best practices? by ihb
in thread Context aware functions - best practices? by Aristotle

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2024-03-28 19:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found