跳至内容

捕获块

块可以被捕获并转换为 Proc,它表示一个带有相关上下文(闭包数据)的代码块。

要捕获一个块,您必须将其指定为方法的块参数,为其命名并指定输入和输出类型。例如

def int_to_int(&block : Int32 -> Int32)
  block
end

proc = int_to_int { |x| x + 1 }
proc.call(1) # => 2

上面的代码在 block 变量中捕获传递给 int_to_int 的代码块,并将其从方法中返回。proc 的类型是 Proc(Int32, Int32),一个接受单个 Int32 参数并返回 Int32 的函数。

这样,块可以作为回调保存

class Model
  def on_save(&block)
    @on_save_callback = block
  end

  def save
    if callback = @on_save_callback
      callback.call
    end
  end
end

model = Model.new
model.on_save { puts "Saved!" }
model.save # prints "Saved!"

在上面的示例中,&block 的类型没有指定:这仅仅意味着捕获的块不接受任何参数也不返回任何东西。

请注意,如果返回值类型没有指定,则从过程调用中不会返回任何东西

def some_proc(&block : Int32 ->)
  block
end

proc = some_proc { |x| x + 1 }
proc.call(1) # => nil

要返回一些东西,要么指定返回值类型,要么使用下划线来允许任何返回值类型

def some_proc(&block : Int32 -> _)
  block
end

proc = some_proc { |x| x + 1 }
proc.call(1) # 2

proc = some_proc { |x| x.to_s }
proc.call(1) # "1"

break 和 next

returnbreak 不能在捕获的块内使用。next 可以使用,它将退出并给出捕获的块的值。

with ... yield

捕获的块内的默认接收器不能通过使用 with ... yield 来改变。