Best explanation of Ruby blocks? [closed] Best explanation of Ruby blocks? [closed] ruby ruby

Best explanation of Ruby blocks? [closed]


I offer up my own explanation from this answer, slightly modified:

"Blocks" in Ruby are not the same as the general programming terms "code block" or "block of code".

Pretend for a moment that the following (invalid) Ruby code actually worked:

def add10( n )  puts "#{n} + 10 = #{n+10}"enddef do_something_with_digits( method )  1.upto(9) do |i|    method(i)  endenddo_something_with_digits( add10 )#=> "1 + 10 = 11"#=> "2 + 10 = 12"...#=> "9 + 10 = 19"

While that code is invalid, its intent—passing some code to a method and having that method run the code—is possible in Ruby in a variety of ways. One of those ways is "Blocks".

A Block in Ruby is very, very much like a method: it can take some arguments and run code for those. Whenever you see foo{ |x,y,z| ... } or foo do |x,y,z| ... end, those are blocks that take three parameters and run the ... on them. (You might even see that the upto method above is being passed a block.)

Because Blocks are a special part of the Ruby syntax, every method is allowed to be passed a block. Whether or not the method uses the block is up to the method. For example:

def say_hi( name )  puts "Hi, #{name}!"endsay_hi("Mom") do  puts "YOU SUCK!"end#=> Hi, Mom!

The method above is passed a block that is ready to issue an insult, but since the method never calls the block, only the nice message is printed. Here's how we call the block from a method:

def say_hi( name )  puts "Hi, #{name}!"  if block_given?    yield( name )  endendsay_hi("Mridang") do |str|  puts "Your name has #{str.length} letters."end#=> Hi, Mridang!#=> Your name has 7 letters.

We use block_given? to see whether or not a block was passed along or not. In this case we passed an argument back to the block; it's up to your method to decide what to pass to the block. For example:

def say_hi( name )  puts "Hi, #{name}!"  yield( name, name.reverse ) if block_given?endsay_hi("Mridang"){ |str1, str2| puts "Is your name #{str1} or #{str2}?" }#=> Hi, Mridang!#=> Is your name Mridang or gnadirM?

It's just a convention (and a good one, and one you want to support) for some classes to pass the instance just created to the block.

This is not an exhaustive answer, as it does not cover capturing blocks as arguments, how they handle arity, un-splatting in block parameters, etc. but intends to serve as a Blocks-Are-Lambdas intro.


Ruby blocks are a way of creating Proc objects which represent code that can be used by other code. Proc objects are instructions between curly braces {} (or do...end phrases for multiline blocks, which have lower precedence than curly braces) which may optionally take arguments and return values (e.g. {|x,y| x+y}). Procs are first-class objects and can be constructed explicitly or attained implicitly as method pseudo-arguments:

  1. Construction as a Proc object (or using the lambda keyword):

    add1 = Proc.new {|x| x+1} # Returns its argument plus one.add1.call(1) # => 2
  2. Passed as a method pseudo argument, either explicitly using the special & last-argument syntax sugar operator or implicitly using a block_given?/yield pair:

    def twice_do(&proc) # "proc" is the block given to a call of this method.  2.times { proc.call() } if procendtwice_do { puts "OK" } # Prints "OK" twice on separate lines.def thrice_do() # if a block is given it can be called with "yield".  3.times { yield } if block_given?endthrice_do { puts "OK" } # Prints "OK" thrice on separate lines.

The second form is typically used for Visitor patterns; data can be passed to the special block arguments as arguments to the call or yield methods.


From Why's (poignant) guide to ruby:

Any code surrounded by curly braces is a block.

2.times { print "Yes, I've used chunky bacon in my examples, but never again!" } is an example.

With blocks, you can group a set of instructions together so that they can be passed around your program. The curly braces give the appearance of crab pincers that have snatched the code and are holding it together. When you see these two pincers, remember that the code inside has been pressed into a single unit. It’s like one of those little Hello Kitty boxes they sell at the mall that’s stuffed with tiny pencils and microscopic paper, all crammed into a glittery transparent case that can be concealed in your palm for covert stationary operations. Except that blocks don’t require so much squinting. The curly braces can also be traded for the words do and end, which is nice if your block is longer than one line.

loop do  print "Much better."      print "Ah. More space!"  print "My back was killin' me in those crab pincers."end

Block arguments are a set of variables surrounded by pipe characters and separated by commas.

|x|, |x,y|, and |up, down, all_around| are examples.

Block arguments are used at the beginning of a block.

{ |x,y| x + y }

In the above example, |x,y| are the arguments. After the arguments, we have a bit of code. The expression x + y adds the two arguments together. I like to think of the pipe characters as representing a tunnel. They give the appearance of a chute that the variables are sliding down. (An x goes down spread eagle, while the y neatly crosses her legs.) This chute acts as a passageway between blocks and the world around them. Variables are passed through this chute (or tunnel) into the block.