如何创建一个可选择占用块的枚举器?我想用一些参数和一个可选块调用一些方法foo
。如果使用块调用它,则应该在块上进行迭代,并且应该在其上执行某些操作,包括给定的参数。例如,如果foo
采用单个数组参数,则对其应用map
给定的块,并返回应用于它的join
的结果,然后它看起来像:
foo([1, 2, 3]){|e| e * 3}
# => "369"
如果在没有块的情况下调用它,它应该返回一个枚举器,Enumerator
的方法(例如with_index
)应该能够应用,并以相应的方式执行块:
enum = foo([1, 2, 3])
# => Enumerator
enum.with_index{|e, i| e * i}
# => "026"
我使用条件定义foo
以查看是否给出了块。很容易实现给出块的情况,但返回枚举器的部分更难。我想我需要实现MyEnum
的子类Enumerator
,并使foo
返回它的实例:
def foo a, &pr
if pr
a.map(&pr).join
else
MyEnum.new(a)
end
end
class MyEnum < Enumerator
def initialize a
@a = a
...
end
...
end
但是调用MyEnum.new
会发出警告消息:Enumerator.new without a block is deprecated; use Object#to_enum
。如果我使用to_enum
,我认为它会返回一个普通的Enumerator
实例,而不是内置特定功能的MyEnum
。最重要的是,我不知道如何实现{ {1}}首先。我该如何实现这样的枚举器?或者,正确的方法是什么?
答案 0 :(得分:3)
你可以这样做。
def foo a, &pr
if pr
a.map(&pr).join
else
o = Object.new
o.instance_variable_set :@a, a
def o.each *y
foo @a.map { |z| yield z, *y } { |e| e }
end
o.to_enum
end
end
然后我们
enum = foo([1,2,3])
enum.each { |x| 2 * x } # "246"
或
enum = foo([1,2,3])
enum.with_index { |x, i| x * i } # "026"
灵感来自Enumerator documentation。请注意,您对此类枚举器的所有期望都要求保留,因为.to_enum
负责处理所有这些问题。 enum
现在是合法的Enumerator
!
enum.class # Enumerator