メソッドとローカル変数

DXRubyFrameworkではSpriteクラスのデータにアクセスするのにself.を付けないといけないことになっている。
なぜかというと、Rubyではx=メソッドなどの呼び出しがローカル変数への代入と解釈されてしまうからだ。

class Hoge
  def x=(obj)
    @x = obj
  end

  def x
    @x
  end

  def test1
    x
  end

  def test2
    x=10
    x
  end
end

foo = Hoge.new
foo.x = 5

p foo.test1 # =>5
p foo.test2 # =>10
p foo.x     # =>5

@xに5を入れて、test1は5になる。これはメソッドが呼ばれている。
test2では10を入れて、xを取り出すことはできているように見える。
が、そのあとのfoo.xで5が返っているということは、test2の代入先はローカル変数であって、そこでのxもローカル変数からの取り出しとなっているわけだ。
メソッドを呼び出すためにはself.x=と書かなければならない。
Rubyの仕様として、クラス内の記述の場合にインスタンスメソッドとローカル変数の名前が区別つかないというのは、前からわかりにくいと思っていた。
しかしこうなってくると、わかりにくいというレベルの話ではない。
自由度という点では、self.x=と書けば呼べるんだし、ローカル変数xが定義されていてもself.xとxで使い分けができるから、これでいいのかもしれない。


こういうコードで、クラス内でx=を使うことは通常は無い。
それこそ@x=で代入すればいいからだ。
DXRubyFrameworkがインスタンス変数を使わないのは、Cからインスタンス変数にアクセスしたくないという速度的な事情による。
インスタンス変数を回避しても、x=が使えない。
俺としてはx=がローカル変数への代入なのかメソッド呼び出しなのかがわからないから、クラス内ではあまり使いたくなくて、できれば@x=という形でインスタンス変数に入れたい。
が、遅い。
ということをだらだら考えて、速度を優先してself.x=と書くことにしたのだ。
ローカル変数じゃないということがハッキリわかるから、これはこれでいいのかもしれない。
ちょっと面倒だけど。


実行速度を最優先にして仕様を定めるっつーのは、Rubyの拡張ライブラリでも前例があまりないのではなかろうか。
アルゴリズムとかデータ構造とかじゃなく、実装レベルの実行速度の影響がでかすぎるのだ。
何も考えてないRuby → 使いやすさ重視の拡張ライブラリ → アルゴリズムを工夫したRuby → 超えられない壁 → 速度優先で仕様を定めた拡張ライブラリ
という感じで速くなると考えられる。
DXRubyFrameworkはそーいうものなのだ。