"Jamis Buck" <jgb3 / email.byu.edu> schrieb im Newsbeitrag
news:1070640684.3565.10.camel / localhost...
> I've been wishing there were an easy to way to access Ruby's call
> stack.  I mean, you can use "caller", but that just gives you an array
> of strings.  Sometimes it would be nice to know the file, line, method
> and object that invoked a particular method, without having to parse the
> caller strings.  The object and/or class cannot even be obtained that
> way.
>
> Is there an easy way?  I wound up adding a trace function that
> "listened" for call and return events, and then added them to a custom
> stack.  This worked very well, but is not very robust since if anyone
> sets a new trace function, the "call stack" is no longer accurate.
>
> Here's my solution:
>
> #-------------------------------------------------
> def invoker
>   Thread.current[:callstack] ||= []
>   ( Thread.current[:callstack][-3] || Object )
> end
>
> set_trace_func proc { |event,file,line,obj,bind,klass|
>   if event == "call"
>     Thread.current[:callstack] ||= []
>     Thread.current[:callstack].push klass
>   elsif event == "return"
>     Thread.current[:callstack].pop
>   end
> }
> #-------------------------------------------------
>
> All it tells you is the class of object that invoked the method, but it
> could easily be extended.  What I really want to know is: have I
> reinvented the wheel?  If not, perhaps something like this would be a
> candidate for Rite...?

I don't think you have reinvented the wheel.  I'd do just some little
changes:

module Kernel
  def invoker(levels = -1)
    st = Thread.current[:callstack]
    st && st[levels - 2]
  end
end

set_trace_func proc {|*args|
  case args[0]
  when /call$/
    ( Thread.current[:callstack] ||= [] ).push args
  when /return$/
    Thread.current[:callstack].pop
  end
}

def rec(count)
  p invoker
  puts count
  rec count - 1 if count > 0
end

rec 10

Regards

    robert