Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic nesting of ruby blocks

Tags:

ruby

Imagine i have some resource objects with a run method, which executes the block parameter under the lock held for that resource. For example, like this:

r = Resource("/tmp/foo")
r.run { ... }

How can I write a ruby method which takes an array of resources and executes its block parameter under the lock held for all resources, like:

def using_resources(*res, &block)
  r[0].run do; r[1].run do; r[2].run do ...   

    yield;

  end; end; end; ...
end

Is it possible at all?

like image 265
bvk Avatar asked Jul 29 '09 09:07

bvk


People also ask

What is &Block in Ruby?

The &block is a way of sending a piece of Ruby code in to a method and then evaluating that code in the scope of that method.

How do you pass blocks in Ruby?

In Ruby, methods can take blocks implicitly and explicitly. Implicit block passing works by calling the yield keyword in a method. The yield keyword is special. It finds and calls a passed block, so you don't have to add the block to the list of arguments the method accepts.

What is proc and lambda in Ruby?

Blocks are syntactic structures in Ruby; they are not objects, and cannot be manipulated as objects. It is possible, however, to create an object that represents a block. Depending on how the object is created, it is called a proc or a lambda.

Can you return in a block Ruby?

The return keyword always returns from the method or lambda in the current context. In blocks, it will return from the method in which the closure was defined. It cannot be made to return from the calling method or lambda.


1 Answers

You could also do this using #inject:

def using_resources(*resources, &block)
  (resources.inject(block){ |inner,resource| proc { resource.run(&inner) } })[]
end

As you step through the array, you wrap each resource's invocation of the previous Proc in a new Proc, and then pass that to the next resource. This gets the locks in reverse order (the last resource given is the first one unlocked), but that could changed by using resources.reverse.inject ...

like image 167
rampion Avatar answered Sep 19 '22 21:09

rampion