A block is a syntactical construct, not an object. A Proc is the
object-ized form of a block. If you want to do something on the block,
you need to turn it into an object first.
An analogy might be that the string “def” is a syntactical construct
that creates a method, but it is not itself an object. You can’t write
“def.(…)” and have it be meaningful in this context.
So . . . how does one send a message to the block before it is passed as
an argument? Is that even possible?
You could make it a Proc first and pass that instead. For example, say
you have a method which passes some arguments to a block:
======
def execute(*args, &block); yield *args if block; end
=> nil
execute(1, 2, 3) { |*args| puts “args are: #{args.inspect}” }
args are: [1, 2, 3]
=> nil
======
Instead of supplying the block, you could pass a block argument:
======
printer = lambda { |*args| puts “args are: #{args.inspect}” }
=> #<Proc:0x0000000125eeb8@(irb):12 (lambda)>
execute(1, 2, 3, &printer)
args are: [1, 2, 3]
======
Since printer
is an object, you can call whatever methods you’d like
on it before passing it as a block. Of course, you still need to wind
up with something that looks like a block, or else the yield
won’t
work. For example, you might have a Proc that creates printers
for
you:
======
printer_factory = lambda { |message_prefix| lambda { |*args| puts
“#{message_prefix}: #{args.inspect}” } }
=> #<Proc:0x000000011f9f90@(irb):17 (lambda)>
======
Now we can ask this Proc to create a printer for us, which we’ll then
pass into execute
as a block argument:
======
execute(1, 2, 3, &printer_factory.(“the arguments to this printer are”))
the arguments to this printer are: [1, 2, 3]
======
Make sense?
~ jf
John F.
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: User John Feminella - Stack Overflow