インスタンスが属するクラスをあとから変更する操作を Cyan で
インスタンスが属するクラスをあとから変更する操作をいろいろな言語で - Smalltalkのtは小文字です
parentをさくっと書き換えられるのでお題に書いてある条件だけならクリアできるけど、不要なスロットを消したりまるっとスロットを取っ替えたりできないので残念な感じ。
といってもrubyのremove_methodみたいなのってどういう時に必要になるのか分かってないですすみません。
Cyanには小数やsqrt, sin等の算術関数がないので、座標変換じゃなくて簡単な色空間変換(RGB <=> CMYK)のコードを書いてみた。式はISP imaging-developersから。
mac(copy_slots)^(c, o): `begin: (?o).slots().map^(s, v): slot := Messenger.new(?c, s) Messenger.new(Quote.new(slot), ('x.(=)).message, &(v)).eval() ?c class(RGB)^: def(init)^(&opt r=0, g=0, b=0): $(.r, .g, .b) = &(r, g, b) def(to_cmyk)^(&opt scale = 100): k := scale-scale*(.r.max(.g, .b))/255 $(c, m, y) := if (k == scale): &(0, 0, 0) else: &(*[.r, .g, .b].map^(v){ scale*(scale-scale*v/255-k)/(scale-k) }) CMYK.new(c, m, y, k, scale) def(to_cmyk!)^: copy_slots(self, .to_cmyk()) def(to_s)^: [.r, .g, .b].to_s() class(CMYK)^: def(init)^(&opt c=0, m=0, y=0, k=100, scale=100): $(.c, .m, .y, .k, .scale) = &(c, m, y, k, scale) def(to_rgb)^: RGB.new(*[.c, .m, .y].map^(v){ 255-255*.scale.min(v*(.scale-.k)/.scale+.k)/.scale }) def(to_rgb!)^: copy_slots(self, .to_rgb()) def(to_s)^: [.c, .m, .y, .k].to_s() + "/" + .scale.to_s()
スロットのコピーはもっとマシな書き方がある気が…
以下確認
cyan> load "colors.cy" => true cyan> col1 = col2 = CMYK.new(80, 0, 0, 0, 100) # cyan 80% => #<obj 4e677480> cyan> col1.parent == CMYK => true cyan> col1.to_rgb!() => #<obj 4e677480> cyan> col2.to_rgb!() (stdin):2: error: invalid message for #<obj 4e677480>: to_rgb! cyan> (col1.parent == RGB) && col1.to_s() => "[51, 255, 255]" cyan> (col2.parent == RGB) && col2.to_s() => "[51, 255, 255]" cyan> col2.r = 0 => 0 cyan> col2.to_cmyk!() => #<obj 4e677480> cyan> col1.to_cmyk!() (stdin):2: error: invalid message for #<obj 4e677480>: to_cmyk! cyan> (col1.parent == CMYK) && col1.to_s() => "[100, 0, 0, 0]/100" cyan> (col2.parent == CMYK) && col2.to_s() => "[100, 0, 0, 0]/100" cyan> col2.slots() => %{ parent => #<obj 70ec6700>, c => 100, m => 0, y => 0, k => 0, scale => 100, r => 0, g => 255, b => 255 }