6

Lets say I have the following ruby definition at the topmost level

callable = lambda {"#{hi}"}

and suppose that later on I create an object called temp that has a method called hi. Now what I would like to do is call callable within the context of temp. I have tried doing

temp.instance_eval do callable.call end

but this gives me the error "NameError: undefined local variable or method 'hi' for main:Object". I would like to know if there is any way to rebind the context of callable to temp so that I don't get an error message? I know that I could define method_missing on main:Object and reroute all method calls to temp but this seems like way too big of a hack to accomplish what I want.

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
David K.
  • 6,153
  • 10
  • 47
  • 78

1 Answers1

8

the code you are looking for is

temp.instance_eval(&callable)
Glenjamin
  • 7,150
  • 6
  • 25
  • 26
  • Could you please elaborate on the difference between `temp.instance_eval(&callable)` and `temp.instance_eval do callable.call end`. It seems to me that either one should work but the latter doesn't for some reason. – David K. Jun 28 '10 at 16:07
  • @davidk01: b/c a Proc normally uses the context in which it is defined. instance_eval forces the given proc to use the context of the calling object, but doesn't do so recursively (so procs called w/in that proc are not context-shifted). – rampion Jun 28 '10 at 17:21
  • @rampion: what you said doesn't make sense because `&callable` is also a proc and it does get context-shifted and it actually works properly when we use `instance_eval(&callable)` – David K. Jun 28 '10 at 18:33
  • 1
    @davidk01: Right. `&callable` is the given proc in that case, so it *is* context shifted. `meth(&(lambda { whatever }))` and `meth { whatever }` are equivalent. `meth { lambda { whatever }.call }` is not necessarily equivalent to the other two. – rampion Jun 28 '10 at 18:58
  • @rampion: So what you're saying is that `obj.instance_eval(&callable) != obj.instance_eval {callable.call}` even though in both instances `self` is shifted to `obj`. Incidentally is this a bug or a deliberate implementation choice because my understanding is that `&callable == do callable.call end` – David K. Jun 28 '10 at 19:07
  • 1
    @rampion: Ha, I just got it. Thanks for the explanation it took me a while to figure out what you meant by >but doesn't do so recursively – David K. Jun 28 '10 at 19:30
  • I would explain it as the & being very similar to the * syntax on lists of arguments. The ampersand is sort-of unpacking the proc back into a pure unbound block. (This probaby isn't actually what happens, but behavior-wise this is accurate enough). – Glenjamin Jul 08 '10 at 14:33