#perl リファレンスの作り方
my $r = [@list];
と my $r = \@list;
は、同じようにリファレンスを取るが、前者は一回リスト展開して新しいリストのリファレンスを返してるぜーという話。
$ perl -le 'my @list=(1,2,3); print [@list] for (1..3); print \@list for (1..3);'
ARRAY(0x2292f40)
ARRAY(0x229cb98)
ARRAY(0x229cb80)
ARRAY(0x2292df0)
ARRAY(0x2292df0)
ARRAY(0x2292df0)
\@list
は何回リファレンスをとっても同じ(そりゃそうだ)。
展開してコピーされてるので元のリストは書き換わらない。
$ perl -le 'my @list = (1..10); my $r = [@list]; $r->[0] = 100; print $list[0];'
1
いわゆるリファレンスだとこう。
$ perl -le 'my @list = (1..10); my $r = \@list; $r->[0] = 100; print $list[0];'
100
なので展開する方は遅い。
#!/usr/bin/env perl
use strict;
use warnings;
use Benchmarks sub {
my @ARRAY = (1..100);
return +{
ref => sub {
my $r = [@ARRAY];
},
bs => sub {
my $r = \@ARRAY;
},
};
};
結果。
Benchmark: running bs, ref for at least 1 CPU seconds...
bs: 1.32497 wallclock secs ( 1.32 usr + 0.00 sys = 1.32 CPU) @ 6950787.12/s (n=9175039)
ref: 1.03553 wallclock secs ( 1.04 usr + 0.00 sys = 1.04 CPU) @ 167232.69/s (n=173922)
Rate ref bs
ref 167233/s -- -98%
bs 6950787/s 4056% --
いわゆるリファレンス欲しいだけなのにうっかり展開してるとマイナスでかい。
ハッシュも +{%hash}
とかより \%hash
もちろん、コピーした新しい値のリファレンスが欲しい場合はそれはそれで OK