2.11Ruby语言的块(Block)以及带块的方法

又被称为 代码块 ,位于do~end(包括do和end关键字)或者花括弧{~}(包括花括弧)中间的代码就是 代码块 。代码块不可单独存在,只有出现在一个方法调用之后才是合法的。

程序的控制流首先执行方法,当遇到yield时,控制流会从方法转移到那个与方法调用相关联的代码块中,当程序执行完代码块之后,方法重新获得控制权并且从位于yield之后的第一个语句开始继续执行。如果想给代码块传递实参,可以在yield后面放上一个由逗号分隔的表达式列表。

1.带块的方法的定义

方法名内的形参和yield内的实参都是可选的。

def 方法名(方法形参)
  .
  .
  yield (块实参)
  .
  .
end

2.带块的方法的调用

块变量的作用域在块内部使用(块局部变量)。

#单行语句
对象.方法名(方法实参,···) { |块形参1;块局部变量1,...| 块内容 }
#多行语句
对象.方法名(方法实参,···) do |块形参1;块局部变量1,...| 
  块内容
end

3.作用域

首先回顾一下:方法内的变量被称作局部变量,既然是局部变量,那它的作用域就是方法内,可被方法内的其他成员使用,在方法外不可用。

我们可以把外面的方法暂且称作外围方法,代码块暂且称作嵌套方法,根据局部变量的作用域,外围方法内的方法形参和方法局部变量自然而然可以被该方法内的所有代码块直接使用。代码块既然是嵌套方法,根据局部变量的作用域,只可以在块内部使用,块外部无法访问块级局部变量。

所以,如果一个代码块对一个已经在它外部定义过的变量进行赋值,那么不会创建一个新的块级局部变量,而是将新值赋值给那个已经存在的方法局部变量。

有时候,虽然给我们带来了便利,但是有些时候,我们并不想在代码块内修改外围的方法局部变量,只需要在块形参后面加上分号,分号后面接块级局部变量。

x = y = 0
1.upto(4) do |x;y|
  y = x + 1
  puts y*y
end                 #4,9,16,25
[x,y]               #[0,0]

4.示例

不带yield实参

def myloop
  while true
    yield
  end
end
num = 1                 
myloop do               
  puts "#{num}"  
  break if num > 10     
  num *= 2              
end
#1,2,4,8

带yield实参

def sequence(n,m,c)
  i = 0
  while(i < n)
    yield m*i+c
    i += 1
  end
end

sequence(3,5,1) { |y| puts y }    #1,6,11

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/ruby/rubybasic/1547.html

发表评论

登录后才能评论