http://www.perlmonks.org?node_id=641613

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

Update:

As-of sidhekin's note on "Don't use it if you don't mean it", the selected resolution of omitting the prototype from foo -- which I was actually doing to make things work -- is now established as the de facto standard. Following C standards for Perl is clearly a dangerous path to follow.

If the lecture Gratuitous use of Perl Prototypes hadn't ended with a self-satisfied snigger, I might have even ++'ed it.

Correction "4" => "four", typo cut/paste from an earlier version of foo.pl, where I had passed it through the gotse operator as an attempt at listifying it.

-- snip --

Here's one that had me scratching my head for some time. Background follows:

  1. I have a function definition that takes a list, does some "stuff" to the first element, and returns the revised list:
    sub foo($@) { my ( $first, @other ) = @_; # do something to $first return( $first, @other ); }
  2. The list I want to pass to foo() is somewhat hairy, so I decided to protect it with qw(), e.g.:
    print foo( qw( one two three four ) ), "\n";
  3. When executed, however, I don't get what I wanted, which is a catenation of ("munged one", "two", "three", "four"). Instead, I get "four".
  4. At this point much head-scratching occurs, until I realize that the prototype for foo() is forcing my qw into a scalar context. Remove the prototype, and bingo! it works.

The problem that I have with this is that I like to use prototypes, as a form of self-documenting code. I even use them in object methods, where they don't get enforced, because I want the reader to know what arguments I expect to receive. Ideally, what I want is to list-ify the qw() results, so they'll be passed through foo() intact.

My copy of the Camel asserts (vol 3, p.778):

There's no "list" function corresponding to scalar since, in practice, one never needs to force evaluation in a list context.

I already have multiple potential workarounds -- changing or eliminating the prototype, isolating "one" from the qw() list, etc. -- but it just doesn't seem "right" to have to do this. I see that Perl6 (http://dev.perl.org/perl6/rfc/175.html) may have a "list" keyword that would solve this cleanly.

Does this mean that I'm really running into a pathological edge case in Perl5, or am I just being boneheaded in my approach to the problem? Is there some (reasonably elegant) way to list-ify the args before they get passed to foo()?