YAPC::Asia::2008

これでも正解ではありますが、perlの場合もっと簡単な方法があります。

各言語間の参照と値渡し - @author pyridoxin
sub swap {
    my ($x , $y) = @_;
    $$temp = $$y;
    $$y = $$x;
    $$x = $$temp
}
[codepad]
sub swap {
  my $tmp = $_[0];
  $_[0] = $_[1];
  $_[1] = $tmp;
}
my ($a, $b) = (1, 2);
print "\$a = $a, \$b = $b\n";
swap($a, $b);
print "\$a = $a, \$b = $b\n";

これは、Referenceが存在しなかったPerl 4以前からの仕様です。

もちろん、

sub swap($$){
  ($_[1], $_[0]) = ($_[0], $_[1]);
}

としてもうまく行きます。

Perl 5以降では、subの書き方として

sub meth{
  my $self = shift; # shift @_ の略
  # ....
}

とか

sub func{
  my ($a, $b, $c) = @_;
  # ....
}

とかという具合に、最初にレキシカル変数に@_の内容をコピーするのが一般的ですが、これは不用意に参照元を書き換えないための工夫とも言えます。

なお、foreachmapなどにおける$_も参照です。

[codepad]
my @a = (0..10);
print join(', ', @a), "\n";
$_ *= 2 for @a;
print join(', ', @a), "\n";
map { $_ + } @a;
print join(', ', @a), "\n";

これまたPerl 5では、

for my $item (@array){
  # ....
}

という書き方がサポートされ、不用意に参照元を書き換える可能性を低くしています。

これ、知ったときには結構ギョっとしたのですが、おかげで末尾参照を手で最適化したりも出来ます。

404 Blog Not Found:perl - to goto or not to goto, that's the continuation
sub _fib_g{
    my ($n, $f1, $f2) = @_;
    return $f2 if $n == 0;
    # _fib_g($n - 1, $f2, $f1 + $f2)
    @_ = ($n - 1, $f2, $f1 + $f2);
    goto  &_fib_g;
}
sub fib_g{ _fib_g(shift, 0, 1) };

ナントカと駱駝は使いよう....

Dan the Refer(ent|rer)