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

Hi, I have heard a coworker's comment about invoking subroutine by f(arg1,arg2,arg3)
is much better practice thatn &f because of argument checking:
she says this call just sends the argument right into the function. But I don't see her point because
I can send a list to arg3 without much effort.
sub f{ my (arg1,arg2,arg3)=@_; .... uses arg1, arg2 arg3 .... }
but i don't see many perl programmers uses this. I just not sure if that statment is true.

Replies are listed 'Best First'.
Re: calling f(arg1,arg2,arg3) better than &f
by ikegami (Patriarch) on Feb 08, 2006 at 17:36 UTC

    What argument checking?

    sub f { my ($arg1,$arg2,$arg3) = @_; .... uses arg1, arg2 arg3 .... } f(); # Works. ($arg1, $arg2 and $arg3 are undef.) f(1,2,3,4); # Works. ('4' is ignored.)

    Maybe you're thinking of prototypes? & causes the prototype to be ignored. Use of & is discouraged for this reason. Then again, most prototypes are discouraged as well (for other reasons).

    Aside from ignoring prototypes, (&f) means something different than f():

    sub f { my ($arg1) = @_; print(defined($arg1) ? $arg1 : '[undef]', "\n"); } sub t1 { print("t1: "); f(); } sub t2 { print("t2: "); &f; } t1('moo'); # t1: [undef] t2('moo'); # t2: moo

    When function f is called using &f (with no arguments), a new @_ isn't created; it shares the @_ of its caller.

    Looking at it from the other direction,
    f(...);
    is equivalent to
    do { local @_ = (...); &f };
    (when no prototypes are involved).

    Update: Added talk of prototypes.

      Thanks. But why we want to share @_ with the caller? Please enlighten me. I am a true newbie in perl. Thanks
        Sometimes, you want to pass the arguments you received on to the called function. It's more efficient than creating a new @_. Even more efficient is goto(&f) which returns directly to the caller. Both of these tricks are useful when dealing with advanced features and techniques such as AUTOLOAD and currying. This is not something one commonly does, so & is rarely required.
Re: calling f(arg1,arg2,arg3) better than &f
by DrWhy (Chaplain) on Feb 08, 2006 at 18:07 UTC
    Like just about every other Perl construct, there are times when it makes sense to use &f and others when it doesn't. This construct reuses the current @_ as it's argument list. This can be handy if you want the called function to have some effect on the caller's argument list which the caller will subsequently need to make use of. In most other contexts, it is probaby more clear to f(@_) explicitly so that what is happening is more clear. The effiency differences between &f and f(@_) are negligible except in the most extreme cases, though f(@_) does do extra work to construct a new @_ for f to use.

    Your coworker's reference or 'argument checking' is probably referring to the fact that when you call a function as &f then any prototype it has is ignored. This isn't relevant if you have not established a prototype for the function in question, so your coworkers criticism does not apply. It is probably a bad idea to call a prototyped functions as &f as confusion is indeed likely to occur.

    --DrWhy

    "If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."

      Hi I have got another explanation that Using & means that it's a user defined subroutine. For example:
      &print is a user define print and will not use Perls print function.
      Also, if you don't specify the "&", subroutines must be defined before you make a call to it.
      But from PErl Best Practise:
      sub lock{ my ($file)=@_; print " user defined lock\n"; } sub link{ my ($text, $url) =@_; print " user defined link $text $url\n"; } print "calling lock: ".lock; #calls locl, built-in lock hidden; print "calling &lock: ".&lock; # calls user defined lock print "calling &link: ".&link("123","123"); # user defined link print "calling &link: ".&link; #user defined won't print 123 print "calling link: ".link("123","123"); # built-in link
      So my question: is this a strong case for using &?
Re: calling f(arg1,arg2,arg3) better than &f
by pKai (Priest) on Feb 08, 2006 at 22:03 UTC

    TheDamian has a lot to say about subroutines in Perl in "Perl Best Practices", among others about prototypes, argument checking and sigil calling.

    This is chapter 9 of said Book.

    Incidentally, this excact chapter can be downloaded as pdf for free as a sneak preview from its publisher's web site.

Re: calling f(arg1,arg2,arg3) better than &f
by eff_i_g (Curate) on Feb 09, 2006 at 00:01 UTC
    I use &function_name for writing to multiple files. So if I have:
    sub write_log { ... } sub write_error { ... }
    Instead of placing the following in my script:
    write_log('string'); write_error('string');
    I can keep it cleaner by simply having:
    write_all('string');
    With write_all defined as:
    &write_log; &write_error;