tags:

views:

77

answers:

3

When using Proc#call to call a lambda function in Ruby, self always ends up with the value that it had when the function was defined, rather than the value it has when the function is called, for example:

$p = lambda { self }

class Dummy
  def test
    $p.call
  end
end

d = Dummy.new

> d.test
=> main

Calling test returns main, when what I intended it to return is #<Dummy:0xf794> - an instance of Dummy, which was the value of self at the point in the code where I called $p.

In Javascript, I would just pass the object that I want to be the "callee" as the first argument to call. Is there any such functionality in Ruby, allowing me to set an arbitrary object, or at least the current value of self, as the new value for self when I call a Proc?

+1  A: 

lambda defines a closure which means it will encapsulate the environment it had when it was defined. If you want self to be the caller just define a regular method or better yet use a block.

ennuikiller
Thanks - I know that lambda creates a closure, and I'd like to retain access to the encapsulated environment, but just override the one special variable `self`. Do you have any ideas on how I could do this?
Tobias Cohen
A: 

I don't really understand what you want to do, but in Ruby you can use blocks.

class Dummy
  def test(&block)
    yield self if block_given?
    self
  end
end

d = Dummy.new
d.test
=> #<Dummy:0x7740c>

d.test do |s|
  p s
  # => #<Dummy:0x7740c>
  # you can call all Dummy methods on s
  # s.class, s...
end
Simone Carletti
From what I understand blocks/Procs/lambda are all quite similar. What I want to is override `self` when calling the Proc (or block), so I could just write something like `p to_s` in the block, instead of having to pass `s` as an argument.
Tobias Cohen
+1  A: 

You're looking for instance_eval, which evaluates a lambda in the context of the calling object.

>> $p = lambda { self }
=> #<Proc:0x95cece4@(irb):1 (lambda)>
>> class Dummy
>>   def test
>>     $p.call
>>   end
>> 
>>   def test1
>>     instance_eval(&$p)
>>   end
>> end

>> d = Dummy.new
=> #<Dummy:0x946f7c8>
>> d.test
=> main
>> d.test1
=> #<Dummy:0x946f7c8>
Martin DeMello