Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Comment on

( #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":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

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

    How do I use this? | Other CB clients
    Other Users?
    Others lurking in the Monastery: (10)
    As of 2014-07-28 13:00 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      My favorite superfluous repetitious redundant duplicative phrase is:









      Results (197 votes), past polls