Re: [Tokyo-pm] Re: これはどう動くの?

Dan Kogai dankogai @ dan.co.jp
2004年 8月 27日 (金) 01:23:45 CDT


モツはちょっと苦手な弾です。

On Aug 27, 2004, at 10:58, Shinya Hayakawa wrote:
> On 2004 8月 27 金曜日 12:41 午前, Dan Kogai wrote:
>> それにしても早川君って「モツ好き」だよなあ....
>
> モツ?...あぁ、gutsってことですね(^^;
>
> いえ、Dumpする場所を追加すると,
> perl -MDevel::Peek -le '@a=qw/a b c/; sub a{Dump \@_; \@_ };  
> $b=a(@a);Dump $b'
> REFCNTは3に増えている事が分かります。
>
> @_ 自身はスクラッチパッド上に確保されるので
> 保存の仕組みはクロージャと全く同じですよね。

うーん、この場合、Storageを確保するのはどこか、というのがツッコミの意図で、この場合Storageが確保されているのは  
closureの場合のsub{}内部ではなく、呼び出し側、すなわちsplit//で生成されたSVだよね、ということです。ただし、このSVをまと 
めたAVは早川君の指摘どおり、@_ということになります。

早川君は@_を、弾は$_[]にそれぞれ注目していたという視点の違いですね。

上記の例で言うと、@Aと@$bはそれぞれ別モノですが、$a[]と$b->[]は同一ということになります....

ん?と書いていると

>> #ただし、$b->[]の各要素のSVのref countは1づつ上がる。
>> #うむむ、むしろこちらの方が不(思議|可解)だ!
>
>
>> 引数スタックに積まれる時にcountが上がるのでしたっけ。
>> 後で調べてみます。

の謎が解けました。各要素はそれぞれ@aより参照が一つ、そして@$bより参照がもう一つあります。図に書くと

           SV
@a[0] --> a  <-- $b->[0]
@a[1] --> b  <-- $b->[1]
@a[2] --> c  <-- $b->[2]

となるわけで、確かにREFCNTは2でないと駄目ですね。AVやHVもまた、各要素(SV)に対する参照が必要ですから。

それにしてもなんでこうツラツラとモツ話をしているかというと、Perlの@_の特殊性にあります。実はPerlでは@_そのものはscratch  
padに確保されますが、それの各要素、$_[]は引数のコピーではなく参照なのです。ですから

sub inc{ $_[0]++ }; my $a = 0; inc($a);

とやると、感覚的には参照渡ししているわけでもないのに、$aは1になります。また$_[]の各要素が参照であるが故に、通常は

sub func{
   my (@args) = @_;
   # ....
}

とか

sub meth{
   my $self = shift;
   # ....
}

とsub{}側でわざわざコピーを作るわけです。Perlでは大昔からそうですが、わたしゃ最初はえらいもんにとまどったものです。しかしこの方法は後に

sub args_as_hash{
   my %args = @_;
}

という手法にも道を開きましたし、高速でもある。今となってはあばたもえくぼですね。

Dan the Camelophilia



Tokyo-pm メーリングリストの案内