4

What dose the ( $$ ) do in this code. I have programmed Perl for a long time but never came across this syntax until recently when I opened a very old Perl .plx file

These rows prevent me from upgrading to a more modern Perl version.

sub help( $$ ){

}

The reason it affects me is because I get an error message stating that the help function was called before it was declared. Any idea of how I can solve this without removing the ( $$ ) block??

Pablo Jomer
  • 9,870
  • 11
  • 54
  • 102

3 Answers3

8

The are called prototypes. This particular one says that the sub routine expects to be called with exactly 2 scalar variables. Although prototypes are sometimes useful, mostly they are not.

If you can drop them depends on the rest of the code...

pavel
  • 3,488
  • 1
  • 20
  • 20
7

That's a function prototype, which is used to specify the number and types of arguments that the subroutine takes. See the documentation.

Since it's in the current documentation, I don't see why it's preventing you from upgrading.

Is the error you're getting help called too early to check prototype? Here's the explanation from the perldiag documentation:

(W prototype) You've called a function that has a prototype before the parser saw a definition or declaration for it, and Perl could not check that the call conforms to the prototype. You need to either add an early prototype declaration for the subroutine in question, or move the subroutine definition ahead of the call to get proper prototype checking. Alternatively, if you are certain that you're calling the function correctly, you may put an ampersand before the name to avoid the warning. See perlsub.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • The reason it affects me is because I get an error message stating that the help function was called before it was declared. Any idea of how I can solve this without removing the ( $$ ) block?? – Pablo Jomer Oct 25 '12 at 08:52
  • See updated answer. But I'm surprised the code ever worked if the calls were before the prototype. – Barmar Oct 25 '12 at 09:11
  • I don't find it surprising that warning/error behavior in a case like this has changed. In Perl, there is no general requirement that a sub's prototype come before the call. This is only a special case relating to enforcing the prototype. – dan1111 Oct 25 '12 at 10:23
  • Perl's prototypes **do not** "specify the number and types of arguments." See [Why are Perl 5's function prototypes bad?](http://stackoverflow.com/questions/297034/why-are-perl-5s-function-prototypes-bad) – Michael Carman Oct 25 '12 at 16:54
2

It's a prototype. The $$ specifies that the help function expects two arguments and that they should each be evaluated in scalar context. Note that this does not mean that they are scalar values! Perl's prototypes aren't like prototypes in other languages. They allow you to define functions that behave like built-in functions: parentheses are optional and context is imposed on the arguments.

sub f($$) { print "@_\n" }
my @a = ('a' .. 'c');
f(@a, 'd'); # prints "3 d"

I'm guessing that the error message you're seeing is

help() called too early to check prototype

which means that Perl saw a call to the function before it saw the declaration of the function and knew about the prototype. This means that the prototype wasn't enforced and the call may not behave as expected.

my @a = ('a' .. 'c');
f(@a, 'd'); # prints "a b c d"
sub f($$) { print "@_\n" }

To fix the error you need to either move the subroutine definition before the call, or add a declaration before the call.

sub f($$); # forward declaration
my @a = ('a' .. 'c');
f(@a, 'd'); # prints "3 d"
sub f($$) { print "@_\n" }

All of this should have absolutely nothing to do with your ability to upgrade to a newer version of Perl.

Michael Carman
  • 30,628
  • 10
  • 74
  • 122