読者です 読者をやめる 読者になる 読者になる

non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

mrubyでselfを呼び出されたメソッドのインスタンスとして実行するには

こんばんは、GW中もどんどんいろいろなセリフを喋るように次男がなってきました。kjunichiです。

背景

mrubyで画像変換処理を行うモジュールmruby-mrmagickを作り始めた。名前の通り、rmagickのAPIをmrubyで使えるように開発を進めている。そこで、今回の疑問にぶち当たった。Rmagickでは、処理の細かなオプションをブロックで指定するAPIになっており、

self.foo=bar

の形式で指定することになっていた。yieldで楽勝と思いきや、selfがyieldだと、メソッドインスタンス変数とはならず、ブロック作成時の例えば、main等で実行されてしまうことがわかった。

mrubyでselfを呼び出されたメソッドインスタンスとして実行するには

class Foo
  @width
  def mon(&blk)
    p self
    blk.call
  end
  def montage(&blk)
    instance_eval(&blk)
    p @width
  end

  attr_accessor :width
end

a=Foo.new
p a
p self
b=a.montage {
  p self
  self.width=100
}

instance_evalを使えば、意図した通りの動作になった。これで、mrmagickの開発が進むかも。