4章.参照渡しと値渡し (その4)
今回は参照渡しをしてみます。ちょっと本に戻ります。p.57の「4.1.2 dRubyでは?」からです。が、Marshalのあたりは、同じようなことを既に確認したような気がしますのでここでは省略します。本に沿って試してみて下さいませ。ここではその続き「p.58 参照の値渡し」から読みます。
Marshal.loadによって直列化したオブジェクトをMarshal.dumpで復元するということは、つまりオブジェクトの複製を作ることにほかなりません。ではdRubyはいつも値渡しなのでしょうか?
実は当たっているとも言えるし違うとも言えます。 dRubyでの参照渡しは、元のオブジェクトの代わりに参照情報を含むオブジェクトを直列化することで実現されます。つまり、参照渡しは参照オブジェクトの値渡しなのです。逆に、もう一方の値渡しは単純にオブジェクトを直列化するだけです。4.1.2 dRubyでは?
ふむふむ。
Hello, World.の実験で使ったDRbObjectを覚えていますか? DRbObjectは元のオブジェクトを参照する情報をもったオブジェクトです。 DRbObjectには目的にごとに二つの生成方法が用意されています。一つはDRbObject.new_with_uriを使ってURIからリモートオブジェクトへの参照を作ることです。もう一つはDRbObject.new(obj)のようにオブジェクトを与え自プロセスのオブジェクトへの参照を作ることです。
4.1.2 dRubyでは?
ふむふむふむ。
DRbObject.new(obj)によって、任意のオブジェクトへの参照オブジェクトを作ります。参照を作るということは、他のプロセスがこの参照をつかってメソッド呼び出しする可能性があるということです。ですから、オブジェクトへの参照を作る前に、DRb.start_serviceによってdRubyのサーバを自プロセスで起動しておかなくてはなりません。
4.1.2 dRubyでは?
ふむふむふむふむふむ!!(こればっか)
元の文章でも充分わかりやすいですが、整理します。ここ、すごい重要な気がします。
4-1. DRbObject.new_with_uriを使ってURIからリモートオブジェクトへの参照を作る
4-2. DRbObject.new(obj)のようにオブジェクトを与え自プロセスのオブジェクトへの参照を作る
なぜなら、そのオブジェクトを他からリモート呼び出しすることがあるから(オブジェクトの実体はクライアントにあるから)
すげ!ちょっと感動します。
確かめてみます。p.60に掲載されているように、ハッシュを公開するサーバーを用意します。
% irb --prompt simple -r drb/drb
>> front = {}
>> DRb.start_service(nil, front)
=> #
>> DRb.uri
=> "druby://yourhost:1426"
はい立ち上げてみました。
前回の値渡しの復習をかねて、文字列をハッシュ(フロントオブジェクト)に登録してみます。
there = DRbObject.new_with_uri('druby://yourhost:1426')
str = "Hello, World."
there[1] = str
これは勿論うまくいく。では次に参照を渡してみます。参照はDRbObjectのことです。
there = DRbObject.new_with_uri('druby://yourhost:1426')
str = "Hello, World."
there[1] = str
there[2] = DRbObject.new(str)
しかしこれではうまくいきません。もしこのまま実行すると
in `current_server': DRb::DRbServerNotFound (DRb::DRbServerNotFound)
というエラーが出てしまいます。
なぜなら、DRb.start_serviceをしていないからです。クライアントからオブジェクトの参照を放り込んでいるということは実体がクライアントにあるということです。なのでメッセージに応答するのはクライアントです。クライアントが他局からのメッセージ呼び出しを受け付けることができないと駄目なので、dRubyのサービスが必要です。これがDRb.start_serviceをしなければならない理由です。
DRb.start_service
there = DRbObject.new_with_uri('druby://yourhost:1426')
str = "Hello, World."
there[1] = str
there[2] = DRbObject.new(str)
これでうまくいきます。
今日はここまで。次回は今回やった参照渡しの部分をもうちょっと詳しく見るつもりです。