Eric Mahurin wrote: > --- Robert Klemme <bob.news / gmx.net> wrote: > >>> define_method, instance_eval, class_eval, module_eval, and >>> maybe others seem to have this special ability - rebind the >>> meaning of self (but not locals) for a Proc. This brings us >>> back to the topic I talked about earlier - unbind/rebind procs. >>> It would be nice if we could do the same thing to a Proc that >>> these methods can do internally: >>> >>> aProc.rebind_self(obj) -> aNewProc # rebind what self is >>> >>> With this, "obj.instance_eval(&proc)" would be equivalent to >>> "proc.rebind_self(obj).call". >> >> Why do you want rebind if the other approach is much simpler? >> >> #instance_eval *always* rebinds self (and only self). > > because you can get a handle on that rebound Proc. You might > want to pass it around or whatever. I see. Although I don't have a use case for this at hand and in fact never missed that. But that might be just my personal experience. >>> Other useful rebindings may be: >>> >>> aProc.rebind_locals(binding) -> aNewProc >>> aProc.rebind_all(binding) -> aNewProc >>> # replace local variables with their current values >>> aProc.unbind_locals -> aNewProc >> >> When do you think will unbind_locals be useful? > > As a replacement for many string evals - which are ugly, > inefficient, and possibly dangerous. Many (most?) times that > you need to eval a string it is because you need to pull in > some local variables to help define the string to be evaled. > Here is the first example of a string eval in the 1.8 library I > found: > > for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > LI OPTION tr th td ] > methods += <<-BEGIN + nO_element_def(element) + <<-END > def #{element.downcase}(attributes = {}) > BEGIN > end > END > end > eval(methods) > > This could be replaced by: > > for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD > LI OPTION tr th td ] > define_method(element.downcase.to_sym , > proc { |attributes={}| > nO_element_def(element) > }.unbind_locals # replace element with constant > ) > end > > Much cleaner, huh? Not really (at least to my eyes). Also, there are some issues: - I don't know what nO_element_def does exactly, but it will have to be rewritten to not create a string with ruby code - Your version might be less efficient. - There might be subtle differences because "element" is pulled into the closure - Also, unbind_locals will remove "element" from the procs bindings >> A proc >> typically needs some >> of the variables bound. As for the rebindings, I would >> prefer a general >> mechanism to transfer state from one binding to another. >> Then one could >> implement all your rebind* methods in terms of that general >> mechanism plus >> do more. Alternatively one could think about conversion >> methods Binding <-> >> Hash. > > Transferring locals might be pretty easy, but transferring the > meaning of self would be more difficult, I think. At least > without making a new Binding (and then you'd still need a way > to rebind it to the original proc). Why do you think that self is special? If there is a general mechanism to transfer state (i.e. bindings) into a binding, any variable can be rebound. I imagine something like proc.binding.bind(:self => whatever, :foo => "bar") eval("self", proc.binding) # -> whatever eval("foo", proc.binding) # -> "bar" <snip/> > Interesting. I assumed that since > class_eval/instance_eval/module_eval all returned the same > "self" that they did the same thing. The only difference I see > is in "def <method> ...". With class_eval, it defines instance > methods and with instance_eval, it defines class methods. > That's kind of strange. Some kind of magic is going on here > other than the changing of self. Definitely. > I was hoping that instance_eval could be used to define class > methods using #define_method, but #define_method does the same > with both - defines instance methods. Anybody know of an > equivalent to #define_method for making class methods? I > couldn't figure out any way to define a class method from a > proc - just out of curiosity. Since a class method is just an instance method of the class: >> class Foo;end => nil >> class <<Foo >> define_method(:bar) {"bar"} >> end => #<Proc:0x10185860@(irb):7> >> ?> Foo.bar => "bar" >> Thanks for the interesting exchange! Kind regards robert