3

Possible Duplicate:
What’s this &block in Ruby? And how does it get passes in a method here?

I dont Understand the &block part, what does it do?

here is an example:

def method_missing(method_name, *args, &block)
  @messages << method_name
  @object.send method_name, *args, &block
end
Community
  • 1
  • 1
Brian Joseph Spinos
  • 2,144
  • 2
  • 18
  • 18

4 Answers4

6

Blocks give you an opportunity to state a callback to pass on to a method.

The & is key here - like @pst mentioned, it "promotes" the block to a Proc and binds the Proc to the variable with the given name.

With &

def time(&block)
  puts block
end

time
# => nil
time { foo }
# => #<Proc:0x00029bbc>

Without &

def time(block)
  puts block
end

time { foo }
# => ArgumentError: wrong number of arguments (0 for 1)
# Because & isn't included, the method instead expected an arguement,
# but as a block isn't a arguement an error is returned.
dsgriffin
  • 66,495
  • 17
  • 137
  • 137
  • Daniel, would you please show a code example? – Brian Joseph Spinos Dec 01 '12 at 00:27
  • 2
    IMHO this is a simple and literal explanation, which is adequate in the given context except there is an alternative way to supply a block as a parameter that I don't know of – bjhaid Dec 01 '12 at 00:31
  • Actually the "&" does NOT "promote" a block to a Proc, its the other way around... it converts EXISTING Procs to a block, so methods that take a block can use them! (the Proc is simply a "saved" block), so you create it: my_proc = Proc.new {|x| ...do something... } ... then you can use it in a method that takes a block: @my_collection.each(&my_proc) – Brian Joseph Spinos Sep 28 '13 at 19:09
4

Answering "And how would I pass it to another method?" comment by Brian:

Like this:

def compose init_value, n=2, &b
  if n==0 then init_value else
    b.call( compose init_value, n - 1, &b )
  end
end

compose 2 do |n| n * n end
#=> 16
compose 2, 4 do |n| n * n end
#=> 65536
compose 2, 4 do |n| n * 0.5 end
#=> 0.125

This is a recursive method that recursively applies the same block to a number several times. Here, the block packaged into b argument gets called, but at the same time it is passed on recursively to compose method, while n argument is decremented by 1. In the same way, b could be passed to any method, like map, reduce, anything.

Whereas, should you not need to pass the block to another method, you could simply use yield:

def apply_block_to_1_2_3
  return yield( 1 ), yield( 2 ), yield( 3 )
end

apply_block_to_1_2_3 { |n| n * n }
#=> [1, 4, 9]

May the force be with you.

Boris Stitnicky
  • 12,444
  • 5
  • 57
  • 74
  • I'm sorry, I still dont get it... P.S. I spent like 30min analizing your code... (...and Im new to Ruby...) – Brian Joseph Spinos Dec 01 '12 at 04:34
  • Can you show something more simple? – Brian Joseph Spinos Dec 01 '12 at 04:34
  • 1
    Brian, this _is_ simple. It is imaginable that you could pinpoint exactly what do you not understand here in the comments, but frankly, if you are having troubles getting this basic code, I suggest that you start at [Matz's guide to Ruby](http://www.rubyist.net/~slagell/ruby/index.html), while afterwards you can continue onto Zed Shaw's "Learn Ruby the Hard Way". – Boris Stitnicky Dec 01 '12 at 07:39
3

It converts the block to a proc object that can be passed on to another method.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
1

when you call a method with a block, there are 2 ways to use that block:

  • call yield inside method
  • convert it into a Proc object by prepending & to it

with second way you can pass it to another method.

so in your case it transforms the given block into a Proc and calling method_name with it.

think of it as you can pass a block just like any argument.