From: Makoto Inada Date: 2007-02-23T01:32:23+09:00 Subject: [ruby-dev:30399] Re: class local instance variable ------=_Part_23176_21722357.1172161919110 Content-Type: text/plain; charset=ISO-2022-JP; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline > というのも、稲田さんの期待の前提となる「そのオブジェクトのイ > ンスタンス変数にはすべてアクセスできる」という仮定は、それそ > のものがアクセスできる範囲を限定する(ので、名称重複があって > も問題にならない)クラスローカルインスタンス変数の存在と矛盾 > するからです。 まさに矛盾なんです。で、私が期待しているのは結局、特異クラスだけは特別扱いをして、自身のクラスローカルインスタンス変数スコープを持たない == 常にオブジェクトのクラスのクラスローカルインスタンス変数スコープを使う == ようにしてはどうだろう、ということです。 「特異クラス」ということで、特異メソッドと instance_eval のケースの両方を含んでいますので、まつもとさんの話の前提である、「メソッドの所属するクラスをクラスローカルインスタンス変数の所属先とする」と対立してしまうわけですが。 この案(?) によると、変数の所属クラスは下のようになります。 class Foo def foo @_foo # (1) Foo end def self.foo_c1 @_foo # (2) Class end end class < wrote: > > まつもと ゆきひろです > > ちょっと考えたんですが、まだ納得できる結論が出ていません。 > > In message "Re: [ruby-dev:30382] Re: class local instance variable" > on Sun, 18 Feb 2007 12:23:18 +0900, "Makoto Inada" > writes: > > |> でも、ここではMerongクラスのローカルインスタンス変数にアクセスできるというのが一般的な期待なんでしょうか。 > | > |私はそう期待します。プログラムを書いていて instance_eval > |を使うときは大抵、既に存在するオブジェクトを直接操作/参照するつもりで書いているので、 > | > |1. 特異クラスの存在を(たとえ知っていても)意識していない、 > |2. そのオブジェクトのインスタンス変数にはすべてアクセスできると思ってしまう、 > | > |というふうに考えています。 > > まず、1についてですが、instance_evalでのターゲットとなるクラ > スが特異クラスでないとまずい局面は確かにあります。たとえば > instance_evalの中でメソッド定義を行った場合、やはり、そのオ > ブジェクトのクラスにメソッドが定義されるのではなく、そのオブ > ジェクトに特異メソッドが定義されるべきでしょう。 > > で、クラスローカルインスタンス変数の対象がどうあるべきかとい > うのは、現時点では私にはよくわかりません。 > > というのも、稲田さんの期待の前提となる「そのオブジェクトのイ > ンスタンス変数にはすべてアクセスできる」という仮定は、それそ > のものがアクセスできる範囲を限定する(ので、名称重複があって > も問題にならない)クラスローカルインスタンス変数の存在と矛盾 > するからです。それぞれのメソッドはその所属するクラスというも > のが存在していて、それをクラスローカルインスタンス変数の所属 > 先として問題ないのですが、instance_evalでのクラスローカル変 > 数の所属先を、そのオブジェクトの特異クラスにするのか、そのオ > ブジェクトのクラスにするのかは悩ましいところです。 > > instance_evalの(クラスローカルインスタンス変数の)ターゲット > を、そのオブジェクトのクラスにするのは(やや実装が面倒なもの > の)不可能ではないのですが、それにどれだけ意味があるのかよく > わからないと言うのが正直なところです。 > > 以下の各箇所でのクラスローカルインスタンス変数はどのクラスに > 所属すべきだと思いますか? > > class Foo > def foo > @_foo # (1) > end > def self.foo_c1 > @_foo # (2) > end > end > > class < def foo_c2 > @_foo # (3) > end > end > > def Foo.foo_c3 > @_foo # (4) > end > > foo = Foo.new > > def foo.foo_i1 > @_foo # (5) > end > > class < def.foo_i2 > @_foo # (6) > end > end > > foo.instance_eval { > def foo_i3 > @_foo # (7) > end > } > > まつもと ゆきひろ /:|) > > ------=_Part_23176_21722357.1172161919110 Content-Type: text/html; charset=ISO-2022-JP Content-Transfer-Encoding: 7bit Content-Disposition: inline
> というのも、稲田さんの期待の前提となる「そのオブジェクトのイ
> ンスタンス変数にはすべてアクセスできる」という仮定は、それそ
> のものがアクセスできる範囲を限定する(ので、名称重複があって
> も問題にならない)クラスローカルインスタンス変数の存在と矛盾
> するからです。
 
まさに矛盾なんです。で、私が期待しているのは結局、特異クラスだけは特別扱いをして、自身のクラスローカルインスタンス変数スコープを持たない == 常にオブジェクトのクラスのクラスローカルインスタンス変数スコープを使う == ようにしてはどうだろう、ということです。
「特異クラス」ということで、特異メソッドと instance_eval のケースの両方を含んでいますので、まつもとさんの話の前提である、「メソッドの所属するクラスをクラスローカルインスタンス変数の所属先とする」と対立してしまうわけですが。
 
この案(?) によると、変数の所属クラスは下のようになります。
class Foo
def foo
   @_foo  # (1) Foo
end
def self.foo_c1
   @_foo  # (2)  Class
end
end

class <<Foo
def foo_c2
   @_foo  # (3)  Class
end
end

def Foo.foo_c3
@_foo    # (4)   Class
end

foo = Foo.new

def foo.foo_i1
@_foo    # (5)   Foo
end

class <<foo
def.foo_i2
   @_foo  # (6)  Foo
end
end

foo.instance_eval {
def foo_i3
   @_foo  # (7)  Foo
end
}
 
同じことの繰り返しになりますが、私にとって特異メソッドというのは 1. 既存のオブジェクトに後からメソッドを付け足せる、2. クラスで定義されているメソッドと比べて何の制限もない、という点で、とてつもなく便利なわけです。
これが、クラスローカルインスタンス変数の導入と暗黙の(*) 特異クラスのおかげで、2番目のメリットがなくなってしまうのが、惜しい。どうせ内部で暗黙に作られている特異クラスなんだから、クラスローカルインスタンス変数のスコープ決定のときも、なかったことしてしまえ、という発想です。
上の例でいうと、特異メソッド foo_i[123] が Foo#foo と同じインスタンス変数 @_foo にアクセスできるのがうれしいわけです。
 
(*) 本当に暗黙なの?暗黙であるべきなの?というのは別に議論されていいと思います。それが eigenclass の意味することなのかもしれませんが。
 
もう一つ。クラスローカルインスタンス変数があるなら、クラスローカルクラス変数があってもいいような気がします。両方あるならスコーピングのルールも両方で統一されるのが、自然でしょう。
今までは、私の頭がごちゃごちゃになるのでクラス変数の方は考えないようにしてきましたが、クラス変数まで考えると、案外見落としていることがあるかもしれません。今後はこちらも含めて考えてみようかと思っています。
 
まとまりありませんが、この辺で。
 
稲田
 
On 2/21/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
まつもと ゆきひろです

ちょっと考えたんですが、まだ納得できる結論が出ていません。

In message "Re: [ruby-dev:30382] Re: class local instance variable"
   on Sun, 18 Feb 2007 12:23:18 +0900, "Makoto Inada" <mak@robustatech.com> writes:

|> でも、ここではMerongクラスのローカルインスタンス変数にアクセスできるというのが一般的な期待なんでしょうか。
|
|私はそう期待します。プログラムを書いていて instance_eval
|を使うときは大抵、既に存在するオブジェクトを直接操作/参照するつもりで書いているので、
|
|1. 特異クラスの存在を(たとえ知っていても)意識していない、
|2. そのオブジェクトのインスタンス変数にはすべてアクセスできると思ってしまう、
|
|というふうに考えています。

まず、1についてですが、instance_evalでのターゲットとなるクラ
スが特異クラスでないとまずい局面は確かにあります。たとえば
instance_evalの中でメソッド定義を行った場合、やはり、そのオ
ブジェクトのクラスにメソッドが定義されるのではなく、そのオブ
ジェクトに特異メソッドが定義されるべきでしょう。

で、クラスローカルインスタンス変数の対象がどうあるべきかとい
うのは、現時点では私にはよくわかりません。

というのも、稲田さんの期待の前提となる「そのオブジェクトのイ
ンスタンス変数にはすべてアクセスできる」という仮定は、それそ
のものがアクセスできる範囲を限定する(ので、名称重複があって
も問題にならない)クラスローカルインスタンス変数の存在と矛盾
するからです。それぞれのメソッドはその所属するクラスというも
のが存在していて、それをクラスローカルインスタンス変数の所属
先として問題ないのですが、instance_evalでのクラスローカル変
数の所属先を、そのオブジェクトの特異クラスにするのか、そのオ
ブジェクトのクラスにするのかは悩ましいところです。

instance_evalの(クラスローカルインスタンス変数の)ターゲット
を、そのオブジェクトのクラスにするのは(やや実装が面倒なもの
の)不可能ではないのですが、それにどれだけ意味があるのかよく
わからないと言うのが正直なところです。

以下の各箇所でのクラスローカルインスタンス変数はどのクラスに
所属すべきだと思いますか?

class Foo
def foo
   @_foo  # (1)
end
def self.foo_c1
   @_foo  # (2)
end
end

class <<Foo
def foo_c2
   @_foo  # (3)
end
end

def Foo.foo_c3
@_foo    # (4)
end

foo = Foo.new

def foo.foo_i1
@_foo    # (5)
end

class <<foo
def.foo_i2
   @_foo  # (6)
end
end

foo.instance_eval {
def foo_i3
   @_foo  # (7)
end
}

                               まつもと ゆきひろ /:|)


------=_Part_23176_21722357.1172161919110--