From: Mauricio Julio Fernandez Pradier [mailto:ferferse / telefonica.net] On
Behalf Of Mauricio Fernandez
Sent: Wednesday, June 07, 2006 2:15 PM
> On Tue, Jun 06, 2006 at 05:40:12AM +0900, why the lucky stiff wrote:
> > On Tue, Jun 06, 2006 at 04:43:10AM +0900, Mauricio Fernandez wrote:
> > > On Tue, Jun 06, 2006 at 04:12:14AM +0900, why the lucky stiff wrote:
> > > >   rb_funcall(obj, rb_intern("instance_eval"), 1, proc);
> > >
> > > I don't think that will work: proc is not a String but a Proc
> (TypeError).
> > >
> >
> > Ohhhh.  I guess define_method can take a proc, though.  Back to ye olde
> cloaker.
> > Based on Guy's example:
> >
> >   wagon$ cat a.c
> >   #include <ruby.h>
> >
> >   static VALUE
> >   rb_proc_bind(VALUE obj, VALUE a)
> >   {
> >       VALUE meth, meta;
> >       VALUE cloaker = ID2SYM(rb_intern("__cloaker__"));
> >       meta = rb_singleton_class(obj);
> >       rb_funcall(meta, rb_intern("define_method"), 2, cloaker, a);
> >       meth = rb_funcall(meta, rb_intern("instance_method"), 1, cloaker);
> >       rb_funcall(meta, rb_intern("remove_method"), 1, cloaker);
> >       return rb_funcall(meth, rb_intern("bind"), 1, obj);
> >   }
> 
> Nice hack :)
> Just for fun, here's another idea:
> 
> 
>     $ cat ieval.c
> 
>     #include <ruby.h>
> 
>     static VALUE instance_eval_proc;
> 
>     static VALUE
>     do_instance_eval(VALUE obj, VALUE proc)
>     {
>       return rb_funcall(instance_eval_proc, rb_intern("call"), 2, obj,
> proc);
>     }
> 
>     VALUE
>     obj_eval_it(int argc, VALUE *argv, VALUE self)
>     {
>       VALUE meth, proc;
>       rb_scan_args(argc, argv, "0&", &proc);
> 
>       return do_instance_eval(self, proc);
>     }
> 
>     void Init_ieval()
>     {
>       VALUE obj;
> 
>       instance_eval_proc = rb_eval_string("lambda{|o,b|
> o.instance_eval(&b)}");
>       obj = rb_funcall(rb_cObject, rb_intern("new"), 0);
>       rb_define_method(rb_cObject, "eval_it", obj_eval_it, -1);
>       rb_const_set(rb_cObject, rb_intern("OBJ"), obj);
>     }
> 
>     $ ruby -rieval -e 'p Object::OBJ; Object::OBJ.eval_it { @b = 12 }; p
> Object::OBJ'
>     #<Object:0xb7e13e14>
>     #<Object:0xb7e13e14 @b=12>
> 

Thanks Mauricio! Something like this I've already invented :) Generally,
almost any feature we can't conveniently use from C, colud be used with
evaluating some string.

> One can still hope matz's reflection ([180647] again) will bring a more
> convenient way to do that, though ;)

It would be the most straightforward way. When it would.

Matz? :)

V.