On Jan 4, 2008 6:43 AM, David A. Black <dblack / rubypal.com> wrote:
> Hi --
>
>
> On Fri, 4 Jan 2008, Brian Mitchell wrote:
>
> > On Jan 3, 2008 10:06 PM, Sam Ruby <rubys / intertwingly.net> wrote:
> >> I'm looking at converting some code over from BlankSlate to BasicObject,
> >> but hit a roadblock: I can't figure out any way to do the equivalent of
> >>
> >> class Foo < BlankSlate
> >>    def initialize
> >>      @secret = 99
> >>    end
> >> end
> >>
> >> foo = Foo.new
> >> foo.instance_eval {@secret}
> >>
> >> Any suggestions?
> >
> > Interesting situation. Part of me would want Ruby to allow something like:
> >
> >  # Doesn't work obviously...
> >  Object.instance_method(:instance_eval).bind(foo).call {@secret}
> >
> > On the other hand, it isn't hard to write a method that can be used to
> > extract information w/o dirtying the interface:
> >
> >  class << BasicObject
> >    def accessor_for(name)
> >      @accessors_for ||= {}
> >      unless @accessors_for[name]
> >        tmp = "__tmp#{Thread.current.object_id}__"
> >        class_eval %[
> >          def #{tmp}
> >            #{name}
> >          end
> >        ]
> >        accessors_for[name] = instance_method(tmp)
> >        undef_method(tmp)
> >      end
> >      lambda {|obj| @accessors_for[name].bind(obj).call}
> >    end
> >  end
> >
> > Now you can use:
> >
> >  BasicObject.accessor_for('@test').call(foo)
>
> However, until the question of the metaclass/Class thing is resolved,
> you end up with this:
>
> irb(main):001:0> class << BasicObject; def x; 1; end; end
> => nil
> irb(main):002:0> String.x
> => 1
>
> In other words, #accessor_for will be defined directly on Class. As
> per the other thread, I believe this must be a bug, but I'm waiting
> for a pronouncement.

Good catch. I think it might be related to [ruby-core:14690].

Brian.