Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best explanation of Ruby blocks? [closed]

Tags:

ruby

block

What is the best explanation for Ruby blocks that you can share?

Both usage and writing code that can take a block?

like image 394
Blankman Avatar asked Feb 06 '11 03:02

Blankman


People also ask

What about closures in Ruby What are they?

In Ruby, closure is a function or a block of code with variables that are bound to the environment that the closure is called. Or in other words, closure can be treated like a variable that can be assigned to another variable or can be pass to any function as an argument.

What are Ruby blocks explain with example?

You assign a name to a block. The code in the block is always enclosed within braces ({}). A block is always invoked from a function with the same name as that of the block. This means that if you have a block with the name test, then you use the function test to invoke this block.

Does Ruby have end blocks?

There are two ways of defining a block in Ruby: The first is using the do.. end keyword, the other is using a pair of curly braces. Do.. end block is mainly used when defining a block of code that spans multiple lines, while curly braces {} are used when defining a block of code that spans a single line.


2 Answers

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}" end  def do_something_with_digits( method )   1.upto(9) do |i|     method(i)   end end  do_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}!" end  say_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 )   end end  say_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? end  say_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.

like image 100
Phrogz Avatar answered Nov 09 '22 16:11

Phrogz


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 proc end twice_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? end thrice_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.

like image 20
maerics Avatar answered Nov 09 '22 15:11

maerics