At 22:23 12/06/2004 +0900, you wrote: >Gavin Sinclair wrote: > >>Something I've wanted to do on a few occasions recently is to evaluate >>an expression in the context of the calling method. > >Use this: > >>begin >> require 'simplecc' >>rescue LoadError >> def Continuation.create(*args, &block) >> cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?} >> result ||= args >> return *[cc, *result] >> end >>end >># This method returns the binding of the method that called your >># method. Don't use it when you're not inside a method. >># >># It's used like this: >># def inc_counter >># Binding.of_caller do |binding| >># eval("counter += 1", binding) >># end >># end >># counter = 0 >># 2.times { inc_counter } >># counter # => 2 >># >># You will have to put the whole rest of your method into the >># block that you pass into this method. If you don't do this >># an Exception will be raised. Because of the way that this is >># implemented it has to be done this way. >>def Binding.of_caller(&block) >> old_critical = Thread.critical >> Thread.critical = true >> count = 0 >> cc, result, error = Continuation.create(nil, nil) >> error.call if error >> tracer = lambda do |*args| >> type, context = args[0], args[4] >> if type == "return" >> count += 1 >> # First this method and then calling one will return -- >> # the trace event of the second event gets the context >> # of the method which called the method that called this >> # method. >> if count == 2 >> # It would be nice if we could restore the trace_func >> # that was set before we swapped in our own one, but >> # this is impossible without overloading set_trace_func >> # in current Ruby. >> set_trace_func(nil) >> cc.call(eval("binding", context), nil) >> end >> elsif type != "line" >> set_trace_func(nil) >> error_msg = "Binding.of_caller used in non-method context or " + >> "trailing statements of method using it aren't in the block." >> cc.call(nil, lambda { raise(ArgumentError, error_msg ) }) >> end >> end >> unless result >> set_trace_func(tracer) >> return nil >> else >> Thread.critical = old_critical >> yield result >> end >>end > >Regards, >Florian Gross This is a very creative piece of work, congratulations ! I am adding that to my rcr.rb with the proper credit. I guess that it is not extremely efficient but it will help me a lot in my exception logging scheme. So far I used to explicitly pass the binding to be able to dump the local variables when required. Thanks ! For more speed demanding usage, there would be some need for native support I guess, but as of today your solution is probably very close to the most efficient solution. BTW: What is "simplecc.rb" ? Yours, JeanHuguesRobert ------------------------------------------------------------------------- Web: http://hdl.handle.net/1030.37/1.1 Phone: +33 (0) 4 92 27 74 17