On Mon, 22 Oct 2001, Robert Feldt wrote:

> Yes, this is a better approach than previous proposals and IMHO the
> "right" way to do it.

It certainly looks cleaner, but to get the binding n levels up looks to be
O(n)?  Generally speaking, I only want the immediate caller's binding
anyway, so this isn't too big a deal.

One disadvantage of both proposals is that having access to the caller's
binding can be VERY dangerous.  But it is already possible to use a hack
to get the caller's binding (as I show below, and as matju has shown in
[ruby-talk:12401], so perhaps a non-hack is a good idea.

Perhaps it would be nice if it were possible to get "read-only access" to
the caller's binding?

> Maybe we should an argument to Binding#caller that will traverse the
> bindings until 0 (either returning them all or just the "last" one). But,
> of course, its trivial with the current proposal.
>
> If its accepted Kernel.caller should probably be deprecated...

Or perhaps implemented in terms of the proposed methods.  There's a lot of
code that depends on caller.  I think I lean toward deprecating it,
because code that uses caller() probably does many evil things (such as
parsing the caller string by hand).

In the meantime, I use the following in my code.  I'm not sure if it works
in 100% of cases; would anyone care to comment?  (Yes, I know it slows
down execution).

$call_stack = []
set_trace_func(proc {|*args|
  case args[0]
    when 'call'
      $call_stack.unshift($current_call)
    when 'return'
      # If we get an exception, we should still get the normal sequence of
      # "return" messages.
      $call_stack.shift()
  end
  $current_call = args
})

def foo; eval("x = 42", $call_stack[1][4]); end
def bar; foo; end
x = nil
bar
puts x # this should display 42

Paul