A detailed explanation of code blocks in Ruby and its parameter transfer _ruby topics

Source: Internet
Author: User
First, the block statement
  Block declarations are enclosed in {..} or do..end after the function call. {} Is generally used for single-line statements, and do..end is used for multi-line statements.

(1..4) .each {| v | print "# {v}"} #Output 1 2 3 4

  Blocks can take parameters. Unlike function parameters, block parameters are encapsulated with ||, of course, they can take multiple parameters. How to define these parameters is actually defined inside the function, which will be described later.

Second, access to variables within the block
  Variables outside the block can be accessed inside the block, that is, variables outside the block are visible inside the block, such as

sum = 0
(1..5) .each do | v |
  name = 'smile' #name belongs to the variable in the block, and its visible range can only be in the block. Assume that there is no variable with the same name outside the block.
  sum + = v #sum is visible inside the block
end
p sum #Output 15, sum has changed.
p name #Error! name is not accessible.

  Because the variables inside and outside the block can be changed, some external variables may be accidentally modified. This is not what we want. Fortunately, after Ruby version 1.9, a safe way is provided to declare variables inside the block, add ";" after the block parameters, and put variables inside the block after ";".

name = 'outside'
sum = 0
(1..5) .each do | v; name | #nameAfter ";", multiple variables can be declared, separated by commas
  name = 'inside' #name belongs to the variable inside the block, and its visible range can only be inside the block. Assume that there is no variable with the same name outside the block.
  sum + = v #sum is accessible within the block
end
p sum #Output 15, sum has changed.
p name #Output outside, unchanged.

Third, the yield statement
  Looking at this, it may not be quite clear how functions call blocks. Now to introduce the call of the block, the key is the yield statement. In the function body, if yield is used, the function calls the function's block.

def threeTime
  yield
  yield
  yield
end
threeTime {p 'Hello world!'}

  Is it easy to output three lines of Hello world !? You should understand now, it is the block called yield.
What is the parameter of the block? It is estimated that you have already thought of it, which is the parameter of yield. Like ordinary functions, yield can take parameters. See example

def takeBlock (p1)
 if block_given? # Determine if there is a block. If you do not declare the block during yield, an error will occur, so it is better to make a judgment here.
  yield (p1) # Pass p1 to the block parameter, which is the s in the block declaration below
 else
  p1
 end
endie
 
takeBlock ("no block") #output "no block"
takeBlock ("no block") {| s | s.sub (/ no /, '')} #output "block"

  Since yield can pass parameters to the block, and vice versa, can the block pass values to yield? The answer is yes. The value of the last sentence in the block is automatically passed to yield. See example

def nTime
 i = yield # return block value on first call
 (0..i) .each {| v | yield (v)} # Here yield can also be placed in a block
end
nTime do | v |
 print "# {v}" if v
 9 #yield number returned when called
end
#Output 1 2 3 4 5 6 7 8 9

Of course, the above example is only used as an example. In fact, no one will define it this way. A better definition is as follows:

def nTime (n)
 (0..n) .each {| v | yield (v)}
end
nTime (9) do | v |
 print "# {v}"
end

Let's look at the find implementation in Array

class Array
 def find
  for i in 0 ... size
   value = self [i]
   return value if yield (value)
  end
  return nil
 end
end
[1, 3, 5, 7, 9] .find {| v | v> 5} #Find the first number greater than 5, and output 7.
 Because of the appearance of blocks, many for statements are missing in Ruby, and the code looks more humane. Writing code is no longer a boring thing, but a pleasure.

Fourth, another way to pass blocks

def fun #without parameters
 yield
end
proc =-> {p 'haha'}
 
fun & proc
#####
def fun2 (x) #with parameters
 yield x
end
proc2 =-> (x) (p x)
fun2 1, & proc2

Five, instance_eval () and instance_exec ()
In Ruby, a very cool feature is provided. You can insert a code block by using Objec # instance_eval (), Objec # instance_exec () methods, make an object context probe (Context Proble), and dive into the code in the object Clips and manipulate them. With this feature, you can easily test the object's behavior and view the current state of the object.

class MyClass
 def initialize
  @v = 1;
 end
end
obj = MyClass.new
obj.instance_eval do
 puts self # => # <MyClass: 0x007fbb2d0299b0>
 puts @v # => 1
end
obj.instance_exec (5) {| x | puts x * @v} # => 5
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.