Re: class local instance variable

こんばんは。朴 芝印 と申します。

初めてなのでどうかよろしくお願いします。

次のようなcodeを実行してみました。
すると、

mithrandir@losrorien ~/ruby/ruby-svn/trunk $ cat test2.rb
class Merong
def m
@y = “Yes!”
end
end

m = Merong.new
m.m
m.instance_eval { @x = “Yes!” }
puts m.instance_variables.inspect

mithrandir@losrorien ~/ruby/ruby-svn/trunk $ ./miniruby test2.rb
[:@x/#<Class:#Merong:0xb7ed95c4>, :@y/Merong]

こうなりました。

何かinstance_evalの中ではちょっとivar2が違うような気がしますがあれが間違ったとすれば、@x/Merong
となるように直したらSingletonも元のコードで動くと思います。
かんちがいだったらすみません。

日本語が下手です、すみません。大目にみてください

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:30362] Re: class local instance variable”
on Sat, 17 Feb 2007 01:31:28 +0900, “Park Ji-In” [email protected]
writes:

|mithrandir@losrorien ~/ruby/ruby-svn/trunk $ cat test2.rb
|class Merong
| def m
| @y = “Yes!”
| end
|end
|
|m = Merong.new
|m.m
|m.instance_eval { @x = “Yes!” }
|puts m.instance_variables.inspect
|
|mithrandir@losrorien ~/ruby/ruby-svn/trunk $ ./miniruby test2.rb
|[:@x/#<Class:#Merong:0xb7ed95c4>, :@y/Merong]
|
|e$B$3$&$J$j$^$7$?!#e(B

instance_evale$B$G$O%/%i%9%m!<%+%k$NBP>]$H$J$k%/%i%9$O!"$=$N%*e(B
e$B%V%8%'%/%H$NFC0[%/%i%9$G$9!#$G$9$+$i!“e(BMeronge$B%/%i%9$N%/%i%9%m!<e(B
e$B%+%kJQ?t$O%”%/%;%9$G$-$^$;$s!#e(B

e$B$G$b!“$3$3$G$Oe(BMeronge$B%/%i%9$N%m!<%+%k%$%s%9%?%s%9JQ?t$K%”%/%;e(B
e$B%9$G$-$k$H$$$&$N$,0lHLE*$J4|BT$J$s$G$7$g$&$+!#%/%i%9JQ?t$N$He(B
e$B$-$K$b$$$m$$$m9M$($^$7$?e(B[1]e$B$,!"F1$8$h$&$J$3$H$r%/%i%9%m!<%+e(B
e$B%kJQ?t$KBP$7$F$b9T$&$Y$-$J$s$G$7$g$&$+!#e(B

[1] http://www.rubyist.net/~matz/20070104.html#p03

稲田です。

でも、ここではMerongクラスのローカルインスタンス変数にアクセスできるというのが一般的な期待なんでしょうか。

私はそう期待します。プログラムを書いていて instance_eval
を使うときは大抵、既に存在するオブジェクトを直接操作/参照するつもりで書いているので、

  1. 特異クラスの存在を(たとえ知っていても)意識していない、
  2. そのオブジェクトのインスタンス変数にはすべてアクセスできると思ってしまう、

というふうに考えています。この文脈から見れば、(暗黙で作られた)特異クラスがあるためにオブジェクトの元クラスのローカルインスタンス変数にアクセスできないというのは、唐突な感じがします。
instance_eval ã§ãªãã¦ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã«ç‰¹ç•°ãƒ¡ã‚½ãƒƒãƒ‰ã‚’è¿½åŠ ã™ã‚‹å ´åˆã§ã‚‚ã€åŒã˜ã‚ˆã†ã«æ„Ÿã˜ã¾ã™ã€‚

これが、明示的にサブクラスを作っていれば、「オブジェクトにはスーパークラスで定義されたアンタッチャブルな部分がある」で簡単に納得できるんですが。

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

e$B$A$g$C$H9M$($?$s$G$9$,!"$^$@G<F@$G$-$k7kO@$,=P$F$$$^$;$s!#e(B

In message “Re: [ruby-dev:30382] Re: class local instance variable”
on Sun, 18 Feb 2007 12:23:18 +0900, “Makoto Inada”
[email protected] writes:

|> e$B$G$b!“$3$3$G$Oe(BMeronge$B%/%i%9$N%m!<%+%k%$%s%9%?%s%9JQ?t$K%”%/%;%9$G$-$k$H$$$&$N$,0lHLE*$J4|BT$J$s$G$7$g$&$+!#e(B
|
|e$B;d$O$=$&4|BT$7$^$9!#%W%m%0%i%$r=q$$$F$$$Fe(B instance_eval |e$B$r;H$&$H$-$OBgDq!"4{$KB8:_$9$k%*%V%8%'%/%H$rD>@\A:ne(B/e$B;2>H$9$k$D$b$j$G=q$$$F$$$k$N$G!"e(B
|
|1. e$BFC0[%/%i%9$NB8:_$r!J$?$H$(CN$C$F$$$F$b!K0U<1$7$F$$$J$$!“e(B
|2. e$B$=$N%*%V%8%'%/%H$N%$%s%9%?%s%9JQ?t$K$O$9$Y$F%”%/%;%9$G$-$k$H;W$C$F$7$^$&!"e(B
|
|e$B$H$$$&$U$&$K9M$($F$$$^$9!#e(B

e$B$^$:!“e(B1e$B$K$D$$$F$G$9$,!“e(Binstance_evale$B$G$N%?!<%2%C%H$H$J$k%/%ie(B
e$B%9$,FC0[%/%i%9$G$J$$$H$^$:$$6ILL$O3N$+$K$”$j$^$9!#$?$H$($Pe(B
instance_evale$B$NCf$G%a%=%C%IDj5A$r9T$C$?>l9g!”$d$O$j!"$=$N%e(B
e$B%V%8%'%/%H$N%/%i%9$K%a%=%C%I$,Dj5A$5$l$k$N$G$O$J$/!"$=$N%
%Ve(B
e$B%8%'%/%H$KFC0[%a%=%C%I$,Dj5A$5$l$k$Y$-$G$7$g$&!#e(B

e$B$G!“%/%i%9%m!<%+%k%$%s%9%?%s%9JQ?t$NBP>]$,$I$&$”$k$Y$-$+$H$$e(B
e$B$&$N$O!"8=;~E@$G$O;d$K$O$h$/$o$+$j$^$;$s!#e(B

e$B$H$$$&$N$b!“0pED$5$s$N4|BT$NA0Ds$H$J$k!V$=$N%%V%8%'%/%H$N%$e(B
e$B%s%9%?%s%9JQ?t$K$O$9$Y$F%“%/%;%9$G$-$k!W$H$$$&2>Dj$O!”$=$l$=e(B
e$B$N$b$N$,%“%/%;%9$G$-$kHO0O$r8BDj$9$ke(B(e$B$N$G!“L>>N=EJ#$,$”$C$Fe(B
e$B$bLdBj$K$J$i$J$$e(B)e$B%/%i%9%m!<%+%k%$%s%9%?%s%9JQ?t$NB8:$HL7=be(B
e$B$9$k$+$i$G$9!#$=$l$>$l$N%a%=%C%I$O$=$N=jB0$9$k%/%i%9$H$$$&$be(B
e$B$N$,B8:
$7$F$$$F!”$=$l$r%/%i%9%m!<%+%k%$%s%9%?%s%9JQ?t$N=jB0e(B
e$B@h$H$7$FLdBj$J$$$N$G$9$,!“e(Binstance_evale$B$G$N%/%i%9%m!<%+%kJQe(B
e$B?t$N=jB0@h$r!”$=$N%
%V%8%'%/%H$NFC0[%/%i%9$K$9$k$N$+!”$=$N%*e(B
e$B%V%8%'%/%H$N%/%i%9$K$9$k$N$+$OG:$^$7$$$H$3$m$G$9!#e(B

instance_evale$B$Ne(B(e$B%/%i%9%m!<%+%k%$%s%9%?%s%9JQ?t$Ne(B)e$B%?!<%2%C%He(B
e$B$r!“$=$N%*%V%8%'%/%H$N%/%i%9$K$9$k$N$Oe(B(e$B$d$d<BAu$,LLE]$J$b$Ne(B
e$B$Ne(B)e$BIT2DG=$G$O$J$$$N$G$9$,!”$=$l$K$I$l$@$10UL#$,$"$k$N$+$h$/e(B
e$B$o$+$i$J$$$H8@$&$N$,@5D>$J$H$3$m$G$9!#e(B

e$B0J2<$N3F2U=j$G$N%/%i%9%m!<%+%k%$%s%9%?%s%9JQ?t$O$I$N%/%i%9$Ke(B
e$B=jB0$9$Y$-$@$H;W$$$^$9$+!)e(B

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
}

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

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

まさに矛盾なんです。で、私が期待しているのは結局、特異クラスだけは特別扱いをして、自身のクラスローカルインスタンス変数スコープを持たない ==
常にオブジェクトのクラスのクラスローカルインスタンス変数スコープを使う == ようにしてはどうだろう、ということです。
「特異クラス」ということで、特異メソッドと 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
の意味することなのかもしれませんが。

もう一つ。クラスローカルインスタンス変数があるなら、クラスローカルクラス変数があってもいいような気がします。両方あるならスコーピングのルールも両方で統一されるのが、自然でしょう。
ä»Šã¾ã§ã¯ã€ç§ã®é ­ãŒã”ã¡ã‚ƒã”ã¡ã‚ƒã«ãªã‚‹ã®ã§ã‚¯ãƒ©ã‚¹å¤‰æ•°ã®æ–¹ã¯è€ƒãˆãªã„ã‚ˆã†ã«ã—ã¦ãã¾ã—ãŸãŒã€ã‚¯ãƒ©ã‚¹å¤‰æ•°ã¾ã§è€ƒãˆã‚‹ã¨ã€æ¡ˆå¤–è¦‹è½ã¨ã—ã¦ã„ã‚‹ã“ã¨ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“ã€‚ä»Šå¾Œã¯ã“ã¡ã‚‰ã‚‚å«ã‚ã¦è€ƒãˆã¦ã¿ã‚ˆã†ã‹ã¨æ€ã£ã¦ã„ã¾ã™ã€‚

まとまりありませんが、この辺で。

稲田