Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a nested yield work? [closed]

Tags:

yield

ruby

I want to write a code that satisfies:

SomeClass.new.execute(method) == 3

and I have:

class SomeClass
  def execute(method)
    def method
     yield
    end
  end
end

method = 1+2

which gives me nil. I'm still very confused about yield. Any help is greatly appreciated.

like image 463
user3052659 Avatar asked Nov 30 '13 19:11

user3052659


3 Answers

You're along the right lines, but your parameter method must be a code block.

You can create a code block in a few different ways. The most common is anonymously, using {...} or do...end. If you want to store the code block in a variable, which you'd need to do to call SomeClass.new.execute(method), you can use Proc.new.

There are other ways of creating blocks (using the lambda syntax), but they are beyond the scope of this question.

This will work using a block stored in a variable:

class SomeClass
  def execute
    yield
  end
end

method = Proc.new { 1+2 }
SomeClass.new.execute(&method) # => 3

Or, more succinctly,

SomeClass.new.execute { 1 + 2 } # => 3
like image 57
joews Avatar answered Nov 14 '22 09:11

joews


You're sort of in the right direction-ish. yield will execute a passed-in block. So you want to do something like this:

class SomeClass
  def execute
    yield
  end
end

And then you can call it like this:

SomeClass.new.execute { 1+2 }
like image 4
Chuck Avatar answered Nov 14 '22 09:11

Chuck


The yield keyword passes control to any block that was passed to the method. You haven't passed any blocks, so there's nothing to do.

You want something like this:

class C
  def execute
    yield    # Pass control to a block that was passed in.
             # Method returns whatever the value of evaluating `b` was.
  end
end

Now you can do:

C.new.execute { 1 + 2 }     # Pass block containing a statement "1 + 2".
# => 3                      # The result of evaluating "1 + 2" is
                            #   returned from the #execute method.

If you want to pass a method object corresponding to the block you want to pass, instead of specifying it anonymously, you can make a lambda:

b = lambda { 1 + 2 }
C.new.execute &b            # Pass an object to #execute that will be used as
# => 3                      #   the block.

Ruby has a few mostly-equivalent ways of making lambdas:

lambda { 1 + 2 }
Proc.new { 1 + 2 }
-> { 1 + 2 }
like image 4
John Feminella Avatar answered Nov 14 '22 11:11

John Feminella