“yield”关键字在Ruby中的作用是什么?

时间:2010-12-01 06:17:54

标签: ruby yield-keyword

我遇到了以下Ruby代码:

class MyClass
    attr_accessor :items
    ...
    def each
        @items.each{|item| yield item}
    end
    ...
end

each方法有什么作用?特别是,我不明白yield的作用。

8 个答案:

答案 0 :(得分:31)

这是一个充实示例代码的示例:

class MyClass
  attr_accessor :items

  def initialize(ary=[])
    @items = ary
  end

  def each
    @items.each do |item| 
      yield item
    end
  end
end

my_class = MyClass.new(%w[a b c d])
my_class.each do |y|
  puts y
end
# >> a
# >> b
# >> c
# >> d

each遍历集合。在这种情况下,它循环遍历@items数组中的每个项目,在我执行new(%w[a b c d])语句时初始化/创建。

yield item方法中的

MyClass.eachitem传递给附加到my_class.each的块。产生的item被分配给本地y

这有帮助吗?

现在,这里有关于each如何运作的更多信息。使用相同的类定义,这里有一些代码:

my_class = MyClass.new(%w[a b c d])

# This points to the `each` Enumerator/method of the @items array in your instance via
#  the accessor you defined, not the method "each" you've defined.
my_class_iterator = my_class.items.each # => #<Enumerator: ["a", "b", "c", "d"]:each>

# get the next item on the array
my_class_iterator.next # => "a"

# get the next item on the array
my_class_iterator.next # => "b"

# get the next item on the array
my_class_iterator.next # => "c"

# get the next item on the array
my_class_iterator.next # => "d"

# get the next item on the array
my_class_iterator.next # => 
# ~> -:21:in `next': iteration reached an end (StopIteration)
# ~>    from -:21:in `<main>'

请注意,在最后next上,迭代器从数组的末尾掉了下来。这是使用块的 NOT 的潜在缺陷,因为如果您不知道数组中有多少元素,您可以请求太多项并获得异常。

each与一个块一起使用将遍历@items接收器并在到达最后一个项目时停止,避免错误,并保持良好和干净。

答案 1 :(得分:15)

当您编写一个带块的方法时,您可以使用yield关键字来执行该块。

例如,each可以在Array类中实现,如下所示:

class Array
  def each
    i = 0
    while i < self.size
      yield( self[i] )
      i = i + 1
    end
  end
end

MyClass#each需要一个阻止。它为实例的items数组中的每个项执行一次该块,并将当前项作为参数传递。

可能会像这样使用:

instance = MyClass.new
instance.items = [1, 2, 3, 4, 5]
instance.each do |item|
  puts item
end

答案 2 :(得分:10)

接收代码块的Ruby方法通过使用yield关键字调用它来调用它。它可以用于迭代列表,但它不是像其他语言中那样的迭代器。

Here是一个很好的解释,可以解释它比我能做到的更好。

答案 3 :(得分:5)

yield告诉ruby调用传递给该方法的块,并为其提供参数。

yield如果未使用块调用该方法,则会产生错误,而return语句不会产生错误。

return只能在Yield返回巨大值的对象时发送单个值。

答案 4 :(得分:5)

根据我的理解,yield从块执行代码。

def name
    puts "A yield will be called with id of 12"
    yield 12
    puts "A yield will be called with id of 14"
    yield 14
end


name {|i| puts "I am called by yield name #{i}"}

输出:

将以id为12

调用yield

我被产量名称12调用

将以id为14

调用yield

我被yield name 14调用

产量如何运作?

因此,name函数运行时,块代码运行的任何地方都会运行。这是name {|i| puts "I am called by yield name #{i}"}

你可以看到有一个单词yield 12 yield运行块内传递12的代码作为i的值。

这是一个游戏示例:

def load_game
    puts "Loading"

    yield

end


load_game { puts "Game loaded" }

这将在打印game loaded后立即打印loading

装载

加载游戏

答案 5 :(得分:4)

实际效果是在MyClass实例上调用.each与在该实例的.items上调用.each相同。

答案 6 :(得分:4)

作为一个新手,通过一些答案让我困惑,直到我打到Abhi的答案。

yield命令暂停执行方法中的代码,而是将控制权传递回调用它的代码块,执行该代码,然后继续执行该方法的其余部分。这是一个为我澄清的例子:

def hello
    puts "hello"
    yield 
    puts "world"
end

hello do
    puts "there"
end 

输出:

您好

世界

答案 7 :(得分:3)

当cpm说它接受阻止并执行它

简单示例:

def my_method
  yield
end


my_method do
  puts "Testing yield"
end

Testing yield
=> nil