tags:

views:

137

answers:

3

We should all be familiar with the problems related to prototypes in Perl. Here are the two biggies:

  • they don't work like prototypes in other languages, so people misunderstand them.
  • they don't apply to all ways of calling a subroutine.

The second item is the one I am curious about at the moment.

I know of two ways to subvert/work around/ignore prototype enforcement when calling a subroutine:

  • Call the sub as a method. Foo->subroutine_name();
  • Call the sub with a leading & sigil. &subroutine_name();

Are there any other interesting cases I've missed?

Udpate:

@brian d foy, I don't particularly want to evade prototypes, but I wondered "how many ways are there to do it?" I ask this question out of curiosity.

@jrockway, I agree with you, and I believe that you have more explicitly and more concisely described my first point regarding the problems with prototypes, that people misunderstand them. Perhaps the problem lies in programmer expectations and not in the feature. But that is really a philosophical question of the sort I don't want to have.

+9  A: 

Call it via a subroutine reference.

sub foo($) { print "arg is $_[0]\n" }
my $sub = \&foo;
$sub->();


Call it before Perl has seen the prototype (important because perl doesn't make you declare subs before use):

foo();
sub foo($) { print "arg is $_[0]\n" }
derobert
Interestingly, `print prototype($sub), "\n";` still prints "$" (the correct prototype).
Chris Lutz
The second one does give a warning: main::foo() called too early to check prototype...
oylenshpeegul
It looks like any call that is determined at runtime steps around them. This makes sense since they are processed at compile time.
daotoad
+2  A: 

Using the goto &name syntax.

Eric Strom
+1  A: 

Type-glob.

sub foo($) { print "arg is $_[0]\n" }
*foo{CODE}()

Also, consider Bar->foo() rewritten in indirect notation:

foo Bar

Any more? c'mon, bring it.

pst