Ruby代码块(Block)

后端开发   发布日期:2025年07月04日   浏览次数:122

 

1、什么是代码块

        在Ruby中,{}或do...end之间的代码是一个代码块。代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上,由yield关键字调用。例如:

  1. [1,2,3,4,5].each { |i| puts i }
  2. [1,2,3,4,5].each do |i|
  3. puts i
  4. end

块变量:以yield关键字调用block也可以传递参数,block中竖线(|)之间给出的参数名用于接收来自yield的参数。

             竖线之间(如上例中的 | i |)的变量被称作块变量,作用和一个正常方法的参数一样

 

2、{}和do...end优先级不同

       在传递一个block时,使用{}传递的block比使用do…end的优先级要高;

为了避免引起歧义,最好使用()将参数括起来。例如:

  1. 1.upto 3 do |x|
  2. puts x
  3. end

是正确的,但是 1.upto 3 {|x| puts x} 编译不通过,应该写成   1.upto(3) {|x| puts x}

 原因:

1.upto 3 do…end 中block会传递到upto方法里面,3会作为一个参数传递给upto

1.upto 3 {|x| puts x} 一句会把3当做函数名,将block传递到这个函数,其返回值作为upto方法的参数,所以编译不过,需加()。

 

3、代码块转化为对象的方法

代码块并不是对象,但可以通过以下三种方法转化为Proc类的对象:

(1)将一个代码块传递给最后一个参数以 & 开始的方法。例:

  1. def meth1(p1, p2, &block)
  2. puts block.inspect
  3. puts block.call
  4. end
  5. meth1(1, 2) { "This is a block" }

(2)使用Proc.new方法,代码块作为参数:

  1. block = Proc.new { "a block" }

(3)调用Kernel.lambda方法:

  1. block = lambda { "a block" }

    前两种方法是等价的,会检查参数的数量,但Proc.new 创建的对象不会;

用 lambda 和 Proc.new 生成的 Proc 对象之间也是有差别的。这个差别与 return 关键字相关。lambda 中的 return 从 lambda 返回。而 Proc.new 中的 return 从外围方法返回。

  1. # 执行后"Never come here"不会被输出,执行p.call相当于在test_proc方法内执行了return语句。
  2. def test_proc
  3. p = Proc.new { return 1 } # test_proc方法返回
  4. p.call
  5. puts "Never come here" # 永远不会执行到
  6. end
  7. # 使用lambda生成的Proc对象执行call方法调用时,return表示从lambda包围得块内返回。
  8. def test_lambda
  9. p = lambda { return 1 }
  10. result = p.call
  11. puts "The value is: #{result}"
  12. end

Note:在一个代码块中执行next语句会导致代码块返回。返回值就是next语句后带的参数。如果next后没有参数,那么返回值为nil。

  1. def meth2
  2. result = yield
  3. p "The block result is #{result}"
  4. end
  5. puts meth2 { next 9 }
  6. pr = Proc.new { next 100 }
  7. puts pr.call
  8. pr = lambda { next }
  9. puts pr.call
  10. 执行结果为:
  11. The block result is 9
  12. 100
  13. nil

4、yield关键字调用代码块

  1. 在方法中可以使用 yield 来执行代码块的内容,就好像传入的代码块是这个方法的一部分一样。每当碰到一个 yield,代码块的内容就会被执行一次,代码块执行结束后,程序会回到 yield 的那一行继续向下执行。
  1. 使用 yield 可以向代码块传递参数,也可以从代码块取回返回值,返回值就是代码块中最后一个表达式的值。
  1. def fibonacii(max)
  2. f1, f2 = 1, 1
  3. while f1 <= max
  4. yield f1
  5. f1, f2 = f2, f1+f2
  6. end
  7. end
  8. fibonacii(1000) { |f| print f, " " }
  9. 执行结果为:
  10. 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

(1)在这个例子中,yield 接收一个参数f1,这个参数将会在执行的时候传递给指定的代码块。在代码块中,接收的参数使用两个竖线括起来放在代码块的头部。

(2)另外,在使用 yield 关键字调用代码块时,如果传入的参数个数少于代码块中定义的参数个数,那么没有传递的参数会自动转为nil。反之,则最后一个参数为一个数组,该数组包含了剩余的传递参数;

以上就是Ruby代码块(Block)的详细内容,更多关于Ruby代码块(Block)的资料请关注九品源码其它相关文章!