青山です。

On Thu, 2 Dec 1999 06:59:05 +0900,
ktokita / ma.neweb.ne.jp wrote:

> でもやっぱり データを命名規則にしたがった変数に格納して、
> 欲しいデータの変数名を作って参照するよりも、
> 規則にしたがったデータ構造をつくって、
> 欲しいデータを直接いぢるほうが美しいと思うんだけどなぁ。
> ま、これも場合によりけりか(^^;

そうですね。結局は場合によりけりですが、適したデータ構造を作る方が良さ
そうという点は同感です。変数名を明かしてユーザーまかせにするよりも、そ
の変数を扱う、適した処理をするメソッドを用意する方が親切そうですしね。

> んー、オンラインドキュメントのどこかをみて認識した事だとおもうのだけど
> 引数は値渡しになるのかと…
> いったいどこを見てそう思ったのだろう(^^;
> 過去ログの紐モデルだとか、そこら辺を流して見て eval.rbでテストして
> (私の)理解と実体を整合させました(^^;

このあたりはまだ決定的な説明が存在しないという感じです。というか、何を
ベースにして話すかによって(相手のベースになる知識によって)変化するよう
なので、複数の説明が存在する事になるようです。

実装に近い、C でのポインタの値渡しあたりをベースにする場合は、ポインタ
の値渡しという事で、値渡しであっています。

一方、実装よりではない、言語仕様をベースにする場合は、このようなポイン
タ渡しを、参照渡しと呼んでいます。言語仕様としては、参照を渡したいので
あり、ポインタを利用しているのは実装の都合でしかないという事ですね。

> > この場合、$object_a の内容をコピーして保持していくため、候補が増えて行
> > くと %object が肥大していくという問題が。
> 
> で、その理解と、昔取った杵柄の perl(もう何年も使ってない(^^;)によると
> コピーして保持していくのは $object_a じゃなくて
> "Hello world!\n"(そして "object_a") だと思うのですが

このあたりはちょっとややこしいのですが、Perl は値ベースなので、
$object_a には値そのもの(のコピー)が入っています。元の文字列を保持させ
るには、$object_a = \"Hello world!\n" のように、値ではなく、参照を取る
必要があります。

そして、$object{'object_a'} = $$object_a のようにすると、$object_a の
値ではなく、$object_a の示す "Hello world!\n" がコピーされて %object
に保持されます。

(とはいえ、%object には結局どちらも値のコピーが入るので、結果に差はあ
りません。)

> で、このコピー元の文字列って(この場合)元々ソースのスクリプトに含まれて
> いるんだから、%objectが肥大していくといっても、せいぜい2倍必要になる
> って事ですよね。

そうですね。

> むしろ、大きな違いは 代入をする時(比較データの設定とか)に、
> 書式として楽な方法を選択すると、バッファコピーのおこる頻度が
> rubyの方が少ないって事ですかね。

そうですね。Perl の場合は値ベースですから、基本的に代入等ではすべて内
容がコピーされますが、Ruby の場合は参照ベースですから、代入等では、そ
れへの参照だけが渡されるので、普通に書くと、メモリ効率は Ruby の方が良
さそうです。

より大きな違いとしては、今回の例で言えば、元の変数の変更に追随するかど
うかという点があります。

$object_a = "Hello world!\n";
%object = ();
$object{"object_a"} = $object_a;
chop($object_a);
print $object_a;                  # --> "Hello world!"
print $object{"object_a"};        # --> "Hello world!\n"

Ruby はリファレンスベースですから、元の内容が変更されても追随します。

object_a = "Hello world!\n"
object = {}
object["object_a"] = object_a
object_a.chop!
print object_a                    # --> "Hello world!"
print object["object_a"]          # --> "Hello world!"

まあ、もっとも、Perl の方もリファレンスを使えば良いだけの事ですけれどね。

$object_a = "Hello world!\n";
%object = ();
$object{"object_a"} = \$object_a;
chop($object_a);
print $object_a;                  # --> "Hello world!"
print ${$object{"object_a"}};     # --> "Hello world!"

より Ruby に近づけて、すべてをリファレンスにすると、こんな感じでしょうか。

$object_a = \"Hello world!\n";
$object = {};
${$object}{"object_a"} = $object_a;
chop($$object_a);
print $$object_a;                 # --> "Hello world!"
print ${${$object}{"object_a"}};  # --> "Hello world!"

書ける事は書けるんですよね。

ただ、このややこしいデリファレンスはちょっと...


-- 
青山 和光 Wakou Aoyama <wakou / fsinet.or.jp>