Issue #1906 has been updated by Yui NARUSE.

Status changed from Open to Assigned
Assignee set to Yukihiro Matsumoto


----------------------------------------
Feature #1906: Kernel#backtrace: Objectifying Kernel#caller
http://redmine.ruby-lang.org/issues/1906

Author: Run Paint Run Run
Status: Assigned
Priority: Normal
Assignee: Yukihiro Matsumoto
Category: core
Target version: 1.9.x


=begin
 Inspired by nobu's recent refactoring of Kernel#rand`, several conversations with Ruby implementors about Kernel#caller, and Rubinius' Backtrace class, I've put together a _rough_ demo of how we could "objectify" Kernel#caller. It's at http://tinyurl.com/m9fdrn [github.com], along with some initial specs.
 
 Rationale
 =========
 
 `caller` has two principle uses: 
 
 * Allowing users to display the backtrace at a given point, e.g. `puts caller`.
 * Introspection to determine the callpath that lead the current method.
 
 The first use is reasonably achievable with `caller`, as long as you don't want to do any formatting of the output. The second is hard because it requires parsing lines of the `caller` Array with regular expressions, and knowing what the various permutations of output imply. It would be easier if we could inspect the call stack with a Ruby-ish API. Further, this would allow alternative implementations to provide this functionality without having to reverse-engineer the output of `caller`. As a result, backtraces would become more useful and code using them more portable.
 
 Name
 ====
 
 The advantage of calling this feature #backtrace is that it's consistent with the usage of the term by Thread and Exception. This, however, could also be construed as a disadvantage because although identically named the output would be materially different. I'm not sure of the best approach in this regard.
 
 API
 ===
 
 A Kernel method named, for sake of argument, 'backtrace' which returns a Backtrace object. It can be treated like an Array, in the same way `caller` is, because it's an Enumerable. It also has shortcuts for accessing the most recent entry on the stack. Each line in the backtrace is represented by a Backtrace::Line object which has #file, #line, and #name accessors which correspond to the filename, the line number, and the method name, respectively. For example:
 
     backtrace.name # The name of the method which invoked the current one as a Symbol
     backtrace.file(2) # The absolute filename of the 3rd entry in the backtrace
     backtrace.each do |line| # Yields Line objects
       puts line.method
     end
     backtrace.lines.select {|l| l.method == :foo} # #lines returns an Array of Line objects
 
 Simple stuff.
 
 Weaknesses
 ==========
 
 Ideally, #name (not called #method because of the clash with Object#method) would return a Method object. One of the many advantages of this would be that we could combine backtraces with Method#parameters to display the signatures of each method. Unfortunately, I can't see a non-hackish way to create Method objects from the output of `caller`, because I don't know which object the method is bound to. but if this were possible it would be useful.
 
 I'm currently throwing away some of the output of `caller` because I don't completely understand it. We'll need to decide whether this would be useful to expose via the API, and if so how.
 
 I'd prefer to return a File object for #file, but the majority of Ruby APIs return pathnames instead, so I've went with convention.
 
 So is there any interest in this type of thing? Is it worth exploring further?
=end



-- 
http://redmine.ruby-lang.org