On 05/20/2012 08:09 AM, sono-io wrote:
        Are there any differences between these two idioms if only one or zero 
arguments are passed to them?
my ($mode) = @_;
my $mode = shift;


If your subroutine needs to know how many arguments were passed, the former style (assignment) makes this trivial. Once @_ has been shifted (latter style), I don't know an easy way to determine if zero or one argument was passed (stack crawling?).


But, this is Perl and there are more than two ways to do it -- you can also access the argument array (@_) directly within your subroutine:

1. Might save some CPU cycles and/or memory. Be sure to benchmark this claim, to see if it's worth the loss of clarity provided by well-named internal variables.

2. Provides call-by-reference semantics -- your subroutine can modify the caller's variables (intentionally or otherwise -- beware!).

3.  Auto-vivifies missing arguments (?).

4.  Blows up if the subroutine tries to modify read-only arguments.


I started using this technique for #1, but soon tripped over the risks of #2. I'm not sure if I was aware of #3 and #4 prior to writing the test code, below.


I also tried testing functions with array arguments -- changing elements (yes, that works) and changing the array length (I got confused).


I concur with Rob's advice for object methods:

On 05/20/2012 08:30 AM, Rob Dixon wrote:
>    my $self = shift;
>    my ($arg1, $arg2) = @_;


Note that Moose around method modifiers use a shift, shift, assignment style.


As always, there is no single best approach for all cases:

1.  Do what makes sense when you write the code, and

2. Try to be consistent so that it is easier to debug and maintain the code later.


HTH,

David

--

2012-05-20 14:08:47 dpchrist@p43400e ~/sandbox/perl
$ cat function_arguments.pl
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Terse = 1;
$| = 1;
sub f_assign {
    my ($a) = @_;
    $a += 1;
}
sub f_direct {
    $_[0] += 1;
}
sub f_shift {
    my $a = shift;
    $a += 1;
}
# main
{
    for my $f (qw( f_assign f_shift f_direct )) {
        my $y = eval { no strict 'refs'; $f->() };
        print "$f() ", $@
            ? "throws exception: $@"
            : 'returns ' . Data::Dumper->Dump([$y], [qw(y)]);
        $y = eval { no strict 'refs'; $f->(10) };
        print "$f(10) ", $@
            ? "throws exception: $@"
            : 'returns ' . Data::Dumper->Dump([$y], [qw(y)]);
        my $xx = my $x = 100;
        print '$x = ', Data::Dumper->Dump([$x], [qw(x)]);
        $y = eval { no strict 'refs'; $f->($x) };
        print "$f(\$x) ", $@
            ? "throws exception: $@"
            : 'returns ' . Data::Dumper->Dump([$y], [qw(y)]);
        print '### side effect: $x is now ',
            Data::Dumper->Dump([$x], [qw(x)])
            if $x != $xx;
    }
}

2012-05-20 14:08:49 dpchrist@p43400e ~/sandbox/perl
$ perl function_arguments.pl
f_assign() returns 1
f_assign(10) returns 11
$x = 100
f_assign($x) returns 101
f_shift() returns 1
f_shift(10) returns 11
$x = 100
f_shift($x) returns 101
f_direct() returns 1
f_direct(10) throws exception: Modification of a read-only value attempted at function_arguments.pl line 12.
$x = 100
f_direct($x) returns 101
### side effect: $x is now 101

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to