Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a bug with Perl's glob prototype?

For no particular reason, I was playing around with the glob prototype (*), and seeing what it would do when the argument is a defined subroutine.

Given the following code:

sub test (*) {print "[@_]\n"}
sub blah ($) {"blah got @_"}

If you write test blah; you get the syntax error Not enough arguments for main::blah...

If you write test blah 1; the program compiles and prints [blah]

If you write test blah die; the program compiles, prints [blah] and does NOT die.

If you write test blah(1); the program compiles and prints [blah got 1]

If you write test blah(die); the program compiles and then dies.

The last two examples are clearly an application of the "if it looks like a subroutine call it is a subroutine call` rule.

However, the parenthesis-less examples seem like a bug to me. Because what seems to be happening is that despite being in glob context, the parser still treats blah as a prototyped function that requires an argument. But when compilation is said and done, the argument to blah is completely thrown away, and the string 'blah' is instead passed to test.

Here is an example of the test blah die; construct run through B::Deparse:

$ perl -MO=Deparse,-p -e 'sub test (*) {print "[@_]\n"} sub blah ($) {"blah got @_"} test blah die;'
sub test (*) {
    print("[@_]\n");
}
sub blah ($) {
    "blah got @_";
}
&test('blah');
-e syntax OK

So as you can see, the die is completely dropped from the op-tree.

So my question is if others consider this behavior a bug? Is the behavior documented anywhere? If it is a bug, is it worth fixing?

like image 772
Eric Strom Avatar asked Apr 08 '11 19:04

Eric Strom


1 Answers

Prototypes in Perl are bad news. They're terribly broken. Actually, they work perfectly, but our mere mortal brains cannot contemplate the full depth of Perl prototypes.

They're suppose to allow you to call a user defined function as if it was a built-in function, but how they work is extremely confusing. See Perldoc persub for how they work (and don't work).

There's been a movement for a while to remove parentheses from Perl function calls, and I guess in some circumstances, removing extraneous parentheses can make the code a wee bit easier to read. However, this tiny improvement isn't big enough to overcome the pitfalls of prototyping.

You're definitely looking at the limits of prototyping. In fact, your code is actually quite confusing, and adding parentheses would improve its readability. Yes, I know that's not your purpose. Your purpose is to contemplate Perl prototyping until you become one with Larry Wall. I appreciate your courage. I experimented with prototyping until I ran crying into my bedroom, slammed the door, and refused to come out until supper. It took years of psychotherapy and heavy drinking to overcome my experience with Perl prototyping. Even today, I'll weep uncontrollably whenever I see \@@.

Perl 6 is suppose to make everything all better. Unfortunately, Perl 6 has been in the works longer than Duke Nukem Forever.

Slight exaggeration. Duke Nukem was actually announced in 1997 while Perl 6 was announced in 2000, so Duke Nukem actually has about three years on Perl 6. But then, Duke Nukem actually has a release date (June 2011) which is more that Perl 6 has.

Okay, enough griping. You're probably better off looking on the Perlmonks site for help. That's where the Perl gurus hang out. They can probably explain everything going on with your program and why it's doing exactly the right thing.

David Weintraub

perl -e 'print "Just another second rate Perl hacker\n";'


ADDENDUM

Seems like the Far More than Everything You've Ever Wanted to Know about Prototypes in Perl has been moved to Perl Monks. That's the article that will explain why your prototypes are behaving as expected.

like image 112
David W. Avatar answered Nov 01 '22 12:11

David W.