我在Ruby中有一个任意方法可以产生多个值,因此可以将它传递给一个块:
def arbitrary
yield 1
yield 2
yield 3
yield 4
end
arbitrary { |x| puts x }
我想修改这个方法,这样,如果没有块,它只是将值作为数组返回。所以这个结构也可以起作用:
myarray = arbitrary
p a -----> [1, 2, 3, 4, 5]
这可以在Ruby中使用吗?
答案 0 :(得分:19)
def arbitrary
values = [1,2,3,4]
return values unless block_given?
values.each { |val| yield(val) }
end
arbitrary { |x| puts x }
arbitrary
答案 1 :(得分:14)
有一种语法:
def arbitrary(&block)
values = [1, 2, 3, 4]
if block
values.each do |v|
yield v
end
else
values
end
end
注意:
yield v
可替换为:
block.call v
答案 2 :(得分:12)
在ruby 1.9+中,您可以使用Enumerator来实现它。
def arbitrary(&block)
Enumerator.new do |y|
values = [1,2,3,4]
values.each { |val| y.yield(val) }
end.each(&block)
end
它的优势在于它也适用于无限流:
# block-only version
#
def natural_numbers
0.upto(1/0.0) { |x| yield x }
end
# returning an enumerator when no block is given
#
def natural_numbers(&block)
Enumerator.new do |y|
0.upto(1/0.0) { |x| y.yield(x) }
end.each(&block)
end
但最常用的方法是用to_enum(your_method_name, your_args)
来保护你的方法:
def arbitrary
return to_enum(:arbitrary) unless block_given?
yield 1
yield 2
yield 3
yield 4
end
这是ruby核心库本身在多个地方使用的习惯用法。