# #perl リファレンスの作り方 {{tag: 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