ひわだです。

From: keiju / Rational.Com (Keiju ISHITSUKA)
Subject: [ruby-dev:7726] Re: new syntax (Re: Re: Ruby 2.0 の話題解禁) 
Date: Thu, 19 Aug 1999 13:45:33 +0900

> けいじゅ@日本ラショナルソフトウェアです.

> >  widget.event_mask("Button-1") = true
> 
> これ意味がとれないですが. あるwidgetの中に"Button-1"というボタンがあって
> そのマスクを設定しているんですかね...
> 
> widget["Button-1"].event_mask = true
> widget.button["Button-1"].event_mask = true
> 
> の方がきれいかなと...

僕の意図は"Button-1"というのは mouse のボタンに対応するイベントの名で、

widget.event_mask |= 0x01  # mouse の左ボタンの press に反応してね

と、現状で書いているところを、

widget.event_mask("Mouse_Button1_Press") = true  # "Mouse_.." が 0x01 に対応

と書けるとうれしいかも、ということでした。

「obj.foo が obj の属性であり、さらにその属性の一部である a を変更した
い、という場合に obj.foo(a) = ... を使う」のはどうだろうか、というのが
今の問題と言っていいかと思います。

上の例は、widget に event_mask という属性があって、その一部である
Mouse_Button1_Press に対応するビットを立てるという操作です。

この例で obj.foo()= 形式を使うのには以下の理由があります。

 1) widget.event_mask |= Widget::EventFlag::Mouse_Button1_Press と書
    いてもいいがユーザが名前空間を指定しなければならない。

 2) widget.set_event_mask("Mouse_Button1_Press", true) よりはいいかも
    知れない。(このへんは感覚なので、否定するわけにはいかない)

 3) event_mask オブジェクトを作るのは大仰に思える。


> >  hiwada.schedule(tomorrow) = "go to the book store."
> 
> これも, Scheduleオブジェクトを用意して
> 
>   hiwada.schedule[tomorrow] = ...

この場合はその通りだと思いますが、クラス数をイタズラに増やしたくない場
合もあるかとは思います。#僕の感覚では、schedule オブジェクトは作って
しかるべきと思いますが、event_mask オブジェクトは作りたくないです。

> >#「foo(a)という属性をvalにする」というなら、"obj.foo[a] = val" のほう
> >#が良さそうですが、互換性が…。
> 
> これは意味が変りますよね.
> 
> (obj.foo)[a]
> 
> obj.fooが存在するような場合, obj.foo(a)はきっと(obj.foo)[a]なのかなと...

僕もそうは思うのですが、obj の属性(のようなもの)が obj から離れても存
在し得てしまう(obj.foo というオブジェクトが独立して存在可能になる)のは
いやな場合もあると思います。

たとえば、こんなクラスを書いて

class EventMask
  Flag = {"Mouse_Button1_Press" => 0x01}
  def initialize(observer_proc); @observer = observer_proc end
  def []=(key, val)
    if val then @event_mask |= Flag[key] else @event_mask &= ~Flag[key] end
    @observer.call(@event_mask)
  end
  def [](key); (@event_mask | Flag[key]) != 0 end
end

しまえばいいわけですが、これが widget から離れて存在するのはいやです。 
それに .event_mask()= が許されれば要らなくなるクラスです。

今の仕様でも、

class AttrAccessor
  def initialize(obj,setter,reader); @obj,@setter,@reader=obj,setter,reader end
  def [](*args); @obj.send(@reader, *args) end
  def []=(*args); @obj.send(@setter, *args) end
end

とかのライブラリを作っといて、

class Widget
  Flag = {"Mouse_Button1_Press" => 0x01}
  def initialize ; @event_mask = 0 end
  def set_event_mask(key, val)
    if val then @event_mask |= Flag[key] else @event_mask &= ~Flag[key] end
  end
  def get_event_mask(key); (@event_mask | Flag[key]) != 0 end
  #private :set_event_mask, :get_event_mask
  def event_mask ; AttrAccessor.new(self,:set_event_mask,:get_event_mask) end
end

とかすれば、button.event_mask[key]=val と使えて、かつ class Button の
側に処理を書けるので*僕的には*問題ないのですが、やはり .event_mask()= 
が許されればこんなややこしいことはしなくてよい。それに AttrAccessor オ
ブジェクトというのがそれだけで存在しうるのはやはりあまり嬉しくない。

というわけで、僕の主張をまとめると、

* 前提として「obj.foo が obj の属性であり、さらにその属性の一部である 
  a を変更したい、という場合にのみ obj.foo(a) = ... を使う」

* obj.foo(a)= を許すことで、class Foo を作る必要がなくなる。foo が obj 
  から離れては意味がないような属性である場合、class Foo がないのはうれ
  しい。

* class AttrAccesor よりは obj.foo(a)= があった方がうれしい人はいるに
  違いない ^^;。

です。

#僕はどちらかというと obj.foo[]= の方が属性っぽくて好きなのですが…。

#あ、ラベル付引数があったら button.set_event_mask(button1:true) の方
#が嬉しそうだ ^^;;;。しまった…。