Explain in depth the quick usage of Block code in Ruby and explain the rubyblock code.
Block
Definition
some_array.each { |value| puts value + 3 }sum = 0other_array.each do |value| sum += value puts value / sumend
- A block is somewhat like the body of an anonymous method
- Block can take parameters
- The Block takes effect only when it is called by method. If the method has parameters, the block appears at the end.
Variables in the Block
If the name of the block's local variables is the same as that of the variables outside the block but in the same scope, the two of them are the same. The value of the variable in the block changes the value of the variable outside the block.
sum = 0[1,2,3,4].each do |value| sum += value puts value / sumendputs sum # => 30
If the block Variable only appears in the block, it is only a local variable in the block and cannot be referenced outside the block.
sum = 0[1,2,3,4].each do |value| square = value * value sum += squareendputs sum # => 30puts square # undefined local variable or method 'square' for main:Object <NameError>Parameters to a block are always local to a block, even if they have the same name as locals in the surrounding scope.value = "some shape"[1,2].each { |value| puts value }puts value# 1# 2# some shapeYou can define a block-local variables by putting them after s semicolon in the block's parameter listsquare = "some shape"sum = 0[1,2,3,4].each do |value; square| square = value * value sum += squareendputs sum # 30puts square # some shape
- By making square block-local, values assigned inside the block will not affect the value of the variable with the same name in the outer scope.
- Blocks for Transactions
- You can use blocks to define a chunk of code that must be run under some kind of transnational control
class File def self.open_and_process(*args) f = File.open(*args) yield f f.close endendFile.open_and_process("testfile","r") do |file| while line = file.gets puts line endend
Blocks Can Be Objects
You can convert a block into an object, store it in variables, pass it around, and then invoke its code later.
If the last parameter of the method has an ampersand (& action), Ruby will find a code block when the method is called, this code block is converted into an object of class Proc.
class ProcExample def pass_in_block(&action) @stored_proc = action end def use_proc(parameter) @store_proc.call(parameter) endendeg = ProcExample.neweg.pass_in_block { |param| puts "The parameter is #{param}" }eg.use_proc(99)# => The parameter is 99def create_block_object(&block) blockendbo = create_block_object { |param| puts "You called me with #{param}" }bo.call 99 # => You called me with 99bo.call "cat" # => You called me with catRuby have two built-in methods that convert a block to an object: lambda and Proc.newbo = lambda { |param| puts "You called me with #{param}" }bo.call 99 # => You called me with 99
- Blocks Can Be Closures
- Closure: Variables in the surrounding scope that are referenced in a block remain accessible for the life of that block and the life on any Proc object created from that block.
Def n_times (thing) lambda {| n | thing * n} endp1 = n_times (23) p1.call (3) # => 69p2. call (4) #=> 92def power_proc_generator value = 1 lambda {value + = value} endpower_proc = power_proc_generatorputs power_proc.call #2 puts power_proc.call #4 lambda expressions lambda {| params | .. .} # It is equivalent to the following statement-> params {...} # parmas is an optional proc1 =-> arg1, arg2 {puts "# {arg1 }#{ arg2}"} proc1.call "hello ", "world" # => hello worldproc2 =-> {"Hello World"} proc2.call # => Hello World
Block Parameter List
Blocks can take default values, splat args, keyword args and a block parameter
proc = -> a, *b, &block do puts "a = #{a.inspect}" puts "b = #{b.inspect}" block.callendproc.call(1,2,3,4) {puts "in block"}# a = 1# b = [2,3,4]# in block