structって何だ
以下のコードがいかにも冗長。
if test.within_circle(x, y, i, j, r) > 0 then old = buf.buf[i][j].r buf.buf[i][j].r = (color.r * fore) + (old * back) old = buf.buf[i][j].g buf.buf[i][j].g = (color.g * fore) + (old * back) old = buf.buf[i][j].b buf.buf[i][j].b = (color.b * fore) + (old * back) end
そうか、こういうときに動的言語のよさってやつ(?)で、レシーバーに送るメッセージのほうをいてレートさせればいいんだと思って、以下のように書き換えた。
if test.within_circle(x, y, i, j, r) > 0 then [:r, :g, :b].each do |col| old = buf.buf[i][j].__send__(col) buf.buf[i][j].__send__(col) = (color.__send__(col) * fore) + (old * back) end end
ところがこれは動かない。Struct固有の問題なのか、何か間違えてるのかよく分からない。struct.cをちらっとのぞくと、structオブジェクトのメンバにアクセスする部分はふつうのメソッドと違ってCでrb_struct_getmemberとか書かれてて何か特殊なのかと思った。でも、
Pixel = Struct.new(:r, :g, :b) p = Pixel.new(1, 2, 3) [:r, :g, :b].each do |col| puts p.__send__(col) end
% ruby test.rb 1 2 3
と普通に動く。むむむ。
代入の左辺に来てはいけないような気がしてきた。つまり、明示的にメソッドを送るとCでいう間接参照になってしまって、アドレスを示すポインタのようなものは戻ってきてないんじゃないかしら。
Pixel = Struct.new(:r, :g, :b) p = Pixel.new(1, 2, 3) [:r, :g, :b].each do |col| p.__send__(col) = 1 end puts p
% ruby test.rb test.rb:4: syntax error, unexpected '=', expecting keyword_end p.__send__(col) = 1 %
なるほど。うーん?
Pixel = Struct.new(:r, :g, :b) p = Pixel.new(1, 2, 3) [:r, :g, :b].each do |col| p.g = 1 end puts p
% ruby test.rb #<struct Pixel r=1, g=1, b=3> %
なるほど。うーむ。