新井です。

In message "[ruby-dev:14605] Re: $stdout への代入 (再考)"
  on 31 Aug 2001 18:19:07 +0900,
  Kazuhiro NISHIYAMA <zn / mbf.nifty.com> wrote:
> In <200108292231.HAA18463 / ums509.nifty.ne.jp>
> On Thu, 30 Aug 2001 07:31:55 +0900
> Koji Arai <JCA02266 / nifty.ne.jp> wrote:
> >         p obj = File.open('/tmp/file', 'w') # => #<File:0x401a6b44>
> >         p obj.fileno                        # => 4
> >         # これ以降の出力は実際には /tmp/file の内容です
> >         p $stdout = obj                     # => #<File:0x401a6b44>
> >         p $stdout.fileno                    # => 4
> >         p STDOUT.fileno                     # => 1
> 
> pなどの出力先は$defoutだと思うのですが、$stdoutと$defoutの
> 関係はどうなっているのでしょうか?
> ドキュメントには$stdoutをかえると$defoutも変わるというのは
> 書いていないようですが。

わかりにくかっただろうとは思うのですが、前のメールで

|	 $stdout = File.open(file, 'w')
|
|    を行うと、以後 $stdout への出力は file への出力になると同時に
|    標準出力(STDOUT)への出力も file への出力になります。ただし、
|    $stdout と STDOUT の fd の値は異なります。

と書いた通りです。$stdout への代入は、通常の代入の効果だけでなく
元の $stdout が指していた IO を代入された IO にリダイレクトする
という厄介な性質があります。元の STDOUT まで変わってしまうわけで
すね。簡単にコードで書けば

	$stdout = foo
は、
	$stdout.reopen(foo)
	$stdout = foo        # <- ここでは普通の代入の意

です。上で reopen を使ってますが、実際に変更するのは fd と出
力先の対応の変更だけなので $stdout.dup2(foo) というメソッド
があるものと考えて置き換えればよいかな。

私の提案は、$stdout への代入に代入の意味をなくそうという案に
なるのでかなり以外な挙動(Rubyの定義とはかけ離れたもの)になっ
てしまうのが難点ですね。コードで書けば

	$stdout = foo
は、
	$stdout.dup2(foo)
です。やっぱやりすぎか。

で、なぜ $stdout に特殊な意味があるかは [ruby-dev:12496] で
まつもとさんが説明されてました。

--
新井康司 (Koji Arai)