Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Calling Functions

by AcidHawk (Vicar)
on Mar 28, 2012 at 07:57 UTC ( [id://962094]=perlquestion: print w/replies, xml ) Need Help??

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

I have been away for the longest time and happened on this comment today.

A bigger issue is using &subname to call subs instead of subname() - that really doesn't do what you think it does. - in this thread Re: What to use instead of global variables

So I wondered what the difference was. I wrote the following as a SIMPLE test to see if anything jumped out at me.

#!/usr/bin/perl use strict; use warnings; print "About to test sub calls using \& --\n"; &test1; print "About to test sub call using name() --\n"; test2(); sub test1() { print "test1: Working\n"; } sub test2() { print "test2: Working\n"; }

When I do a "perl -c myScript.pl" I get the following

main::test2() called too early to check prototype at myScript.pl line 10. myScript.pl syntax OK

And when I run the script it seems to work with no problems. Other than I get the same warning and in the syntax check before the output. Now I do realise that I could simply remove the use warnings; from my script but I was wondering -

  1. What is the warning telling me?
  2. Also what is the difference between calling a function using &subname or subname()
  3. Where in the manual can I RTFM?
  4. Perhaps an simple example showing the different scenarios for using the different ways of calling the function


Of all the things I've lost in my life, its my mind I miss the most.

Replies are listed 'Best First'.
Re: Calling Functions
by AcidHawk (Vicar) on Mar 28, 2012 at 08:01 UTC
    So I found that if I change the code to the following I no longer get the warning,
    #!/usr/bin/perl use strict; use warnings; sub test2() { print "test2: Working\n"; } print "About to test sub calls using \& --\n"; &test1; print "About to test sub call using name() --\n"; test2(); sub test1() { print "test1: Working\n"; }

    So I have to declare the function before I call it.

    "(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."

    So I guess that answers Question 1. Thanks Perlmonks!

    I guess the comment in italics also explains the use of the & then.

    Bah!! I also added use diagnostics; and got the above mentioned paragraph.. it also told me to read perlsub

    So I guess that answers 3 of the 4 questions and I bet that reading perlsub I'll clearly see the reasons you need &subname as apposed to subname()

    Sorry for posting this too quickly!

    Of all the things I've lost in my life, its my mind I miss the most.

      Well done! No, you didn't post too quickly and you gain kudos for posting a follow up with the stuff you found and figured out. Once again: well done!

      The perlsub (I recommend the more up to date perldoc.org link btw) is indeed the place to go for the god oil on this matter, although some of the subtle traps are not really highlighted.

      As you found calling using & ignores prototypes. However as prototypes should almost never be used that is not a big issue. The more subtle potential trap is that the current contents of @_ is used as the argument list to the called subroutine if no explicit arguments are provided.

      True laziness is hard work
      The main thing is that you're using prototypes. Generally prototypes aren't needed, aren't used and can be harmful unless you're very careful. If you define test2 as
      sub test2 { print "test2: Working\n"; }
      you'll find you're able to call it before it's defined, without getting a warning.
Re: Calling Functions
by Happy-the-monk (Canon) on Mar 28, 2012 at 08:37 UTC

    A concise description is in perlsub:

    A subroutine may be called using an explicit & prefix. The & is optional in modern Perl, as are parentheses if the subroutine has been predeclared. The & is not optional when just naming the subroutine, such as when it's used as an argument to defined() or undef(). Nor is it optional when you want to do an indirect subroutine call with a subroutine name or reference using the &$subref) or &{$subref}() constructs, although the $subref->() notation solves that problem. See perlref for more about all that.

    Subroutines may be called recursively. If a subroutine is called using the & form, the argument list is optional, and if omitted, no @_ array is set up for the subroutine: the @_ array at the time of the call is visible to subroutine instead. This is an efficiency mechanism that new users may wish to avoid.

    Cheers, Sören

Re: Calling Functions
by JavaFan (Canon) on Mar 28, 2012 at 09:43 UTC
    For me, the biggest difference is that if you neither use & nor use parenthesis, a mistyped subroutine name will be a compile time error (with strict) or warning (with warnings enabled), instead of a run time error.
    $ perl -Mstrict -wce 'sub f {1;} &g' -e syntax OK $ perl -Mstrict -wce 'sub f {1;} g()' -e syntax OK $ perl -Mstrict -wce 'sub f {1;} g' Bareword "g" not allowed while "strict subs" in use at -e line 1. -e had compilation errors. $ perl -wce 'sub f {1;} g' Unquoted string "g" may clash with future reserved word at -e line 1. Useless use of a constant (g) in void context at -e line 1. -e syntax OK $ perl -Mstrict -wce 'sub f {1;} f' -e syntax OK $
Re: Calling Functions
by andal (Hermit) on Mar 29, 2012 at 07:33 UTC

    Possibly, this goes about special behavior of &func;. For example try this code

    use strict; sub test1 { my $abc = shift; print $abc, "\n"; } sub test2 { print "test2: $_[0]\n"; &test1; test1("from test2"); print "once again:", $_[0], "\n"; } test2("from main");

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://962094]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-03-28 11:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found