On 8/31/07, Dr.Ruud <[EMAIL PROTECTED]> wrote:
snip
> This is nice content, but not presented well, so I wonder how many
> people take the time to read and grok it.
>
> Maybe you can transform it into an article, maybe both on this list and
> on PerlMonks?
>
> (and please give away the answers :)
snip

An article would be redundant, we already have Tom Christiansen's
masterful article "Far More Than Everything You've Ever Wanted to Know
about Prototypes in Perl"*.  It examines prototypes in depth and shows
many of the problems (my examples only show two of them).  As for the
answers,

> > sub foo ($) {

When reading this a naive reader thinks foo takes one argument.  This,
while true, is not what the prototype is saying.  It is saying that
foo takes a scalar argument.  This means anything passed to the
function will be put in scalar context. So, if we pass an array

> > foo(@a);

We are effectively saying

foo(scalar @a);

That is we are passing the number of elements in @a not @a itself.

> > foo(@a[0 .. $#a]);

Again, we are seeing the effects of scalar context, this time on a
list (a slice is list not an array).  This means that the last element
of the list is passed to foo (lists in scalar context yield the last
element**).

> > my $sub = \&foo;
> > $sub->(@a);
> > &foo($a[0], $a[1], $a[2]);

These both are ways to avoid the prototype check altogether.  I don't
know why references to functions don't trigger prototype checking
given that it is legal, but useless, to include them with an anonymous
subroutine:

my $sub = sub ($) { print "args: @_\n" };
$sub->(1,2,3); #not an error

I assume this is because prototypes are checked at compile time rather
than runtime.  I also don't know why the decision was made that
calling functions with & should avoid prototype checking, but I assume
it was because the following was a common pattern once:

sub foo ($) {
    my $n = shift;
    return $n + 5;
}

sub bar ($) {
    die if $_[0] > 10;
    &foo; #call foo with bar's arguments
}

What this all comes down to is that prototypes in Perl are not meant
to be used to control how many arguments a function takes, but rather
what context the function imposes on the code around it.  The fact
that the parser kicks out an error if the context is not met is a side
effect, not the purpose.  And while Larry may have said "The argument
against using an operator for other than its primary purpose strikes
me the same as the old argument that you shouldn't have sex for other
than procreational purposes. Sometimes side effects are more enjoyable
than the originally intended effect.", abusing the side effect is
likely to get you into trouble (STDs, babies, poorly behaving code,
etc.).


* http://library.n0i.net/programming/perl/articles/fm_prototypes/
** I assume this is so that sequences work:
my $a = (func_with_side_effect(), other_side_effect(), result());

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to