自我枚举功能

时间:2015-09-03 11:40:55

标签: ruby enumeration

我有一些代码:

def my_each_with_index
  return enum_for(:my_each_with_index) unless block_given?
  i = 0
  self.my_each do |x| 
    yield x, i 
    i += 1
  end
  self
end

这是我自己的代码,但行:

return enum_for(:my_each_with_index) unless block_given?

在其他人的解决方案中找到。我无法理解他们将函数作为参数传递给enum_for的原因。当我在没有阻止的情况下调用我的函数时,无论有没有enum_for,它都不会返回任何内容。我可以离开......:

return unless block_given?

并且它具有相同的结果。或者我错了吗?

3 个答案:

答案 0 :(得分:1)

在没有阻止的情况下被调用,它将返回一个枚举器:

▶ def my_each_with_index
▷   return enum_for(:my_each_with_index) unless block_given?  
▷ end  
#⇒ :my_each_with_index
▶ e = my_each_with_index
#⇒ #<Enumerator: main:my_each_with_index>

稍后你可以迭代这个枚举器:

▶ e.each { |elem| ... }

此行为在某些情况下特别有用,例如延迟迭代,稍后将块传递给此枚举器等。

只需返回nil即可关闭此功能。

答案 1 :(得分:1)

想想你非常准确的答案。我也很好地了解了其他新开发人员的这个问题:

def iterator
yield 1
yield 2
yield 3
puts "koniec"
end

iterator { |v| puts v }
it = enum_for(:iterator)
puts it.next
puts it.next
puts it.next
puts it.next

只需运行并分析此代码即可。

答案 2 :(得分:0)

对于任何接受块的方法,当没有给出块时,良好的方法实现应具有明确定义的行为。

在您共享的示例中,each_for_index正在由作者重新实现,可能是为了提供额外的语义,或者仅仅为了学术目的,因为它的行为与Ruby的return enum_for(:my_each_with_index) unless block_given? 相同enum_for 3}}

Enumerable#each_with_index的文档有以下内容。

  

使用两个参数(每个项目的项目及其索引)调用块   在枚举。给定参数传递给each()。

     

如果没有给出阻止,则返回枚举器。

为了与突出显示的行保持一致,如果没有给出块,行为应该是什么行为,必须使用类似

的内容
method

Enumerable#each_with_index是一种有趣的方法

  

obj创建一个新的枚举器,通过在str = "xyz" enum = str.enum_for(:each_byte) enum.each { |b| puts b } # => 120 # => 121 # => 122 上调用my_each_with_index进行枚举。

以下是从文档中复制的示例:

each_with_index

所以,如果一个人没有将阻止传递给e = obj.my_each_with_index ... e.each { |x, i| # do something } # `my_each_with_index` executed later ,他们就有机会稍后传递 - 就像人们对my_each_with_index所做的一样。

each_with_index

总之,<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> <h:panelGroup> <p:commandLink id="CID" title="#{messageId}" type="button" value="#{messageId}" ajax="true" actionListener="#{SyncClientPopupBean.setSyncClientById(messageId)}" update="grid" disabled="#{not Shiro.isPermitted('admin:syncclient:read')}" /> <p:overlayPanel for="CID" dynamic="true" at="right top" my="left bottom" appendTo="@(body)"> <p:panelGrid id="grid" columns="2" styleClass="ui-datatable-auto-width"> <...../> </p:panelGrid> </p:overlayPanel> </h:panelGroup> </ui:composition> 尝试与import vincent vincent.core.initialize_notebook() state_topo = "https://raw.githubusercontent.com/wrobstory/vincent_map_data/master/us_states.topo.json" geo_data = [{'name': 'states', 'url': state_topo, 'feature': 'us_states.geo'}] vis = vincent.Map(geo_data = geo_data, scale = 500, projection = 'albersUsa') vis.to_json('vega.json') vis.display() 保持一致,并尝试成为行为良好的API。