From: "青柳政聡" Date: 2011-07-03T12:32:09+09:00 Subject: [ruby-dev:44024] 呼び出し元コンテキストでのselfを取得したい(binding(n = 0)について) 青柳と申します。 こちらに直接投稿していいのか分かりませんが、教えてください。 例えば、以下のObserverパターンのようにコールバックさせるケースでselfを渡すことが多かったので、 これを省略できるように、呼び出し元コンテキストでのselfを取得したいと思っています。 class AObservable include Observable end class AObserver def initialize obj = AObservable.new obj.add_observer(self) # このselfを省略できるようにしたい end def update(arg) end end 色々考えた結果、Bindingを取得できると他にも便利そうと思い、以下でも話題に上がっている binding(n = 0)が実装されると嬉しいのですが、結論がちょっとよく分かりませんでした。 [ruby-dev:3065] [REQ] caller binding [ruby-dev:15990] binding(n = 0) [ruby-dev:32622] binding of caller binding(n = 0)が実装されることはないのでしょうか? もし、実装する予定がない場合、拡張ライブラリで対応しようと考えているので binding_allocを外部から参照可能にして頂きたいのですが、可能でしょうか? ちなみに、ほとんど中田さんのコードから抜き出しただけですが、以下のような実装をしています。 static int caller_level(int argc, VALUE *argv, int minimum) { VALUE v; int level; if (!argc) return minimum; rb_scan_args(argc, argv, "1", &v); level = NUM2INT(v); if (level < 0) { rb_raise(rb_eArgError, "negative caller level: %d", level); } if (level < minimum) { rb_raise(rb_eArgError, "caller level out of range: %d", level); } return level; } static VALUE rb_f_ybinding(int argc, VALUE *argv) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; rb_binding_t *bind; VALUE bindval; int level = caller_level(argc, argv, 0); do { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); cfp = rb_vm_get_ruby_level_next_cfp(th, cfp); if (!cfp) return Qnil; } while (level-- > 0); bindval = binding_alloc(rb_cBinding); GetBindingPtr(bindval, bind); bind->env = rb_vm_make_env_object(th, cfp); bind->filename = cfp->iseq->filename; bind->line_no = rb_vm_get_sourceline(cfp); return bindval; } void Init_yagi_binding(void) { rb_define_global_function("ybinding", rb_f_ybinding, -1); } お忙しい時期かと思いますが、よろしくお願いいたします。