levinalex levinalex - 2 months ago 23
Ruby Question

ruby methods that either yield or return Enumerator

in recent versions of Ruby, many methods in

Enumerable
return an
Enumerator
when they are called without a block:

[1,2,3,4].map
#=> #<Enumerator: [1, 2, 3, 4]:map>
[1,2,3,4].map { |x| x*2 }
#=> [2, 4, 6, 8]


I want do do the same thing in my own methods like so:

class Array
def double(&block)
# ???
end
end

arr = [1,2,3,4]

puts "with block: yielding directly"
arr.double { |x| p x }

puts "without block: returning Enumerator"
enum = arr.double
enum.each { |x| p x }

Answer

The core libraries insert a guard return to_enum(:name_of_this_method, arg1, arg2, ..., argn) unless block_given?. In your case:

class Array
  def double
    return to_enum(:double) unless block_given?
    each { |x| yield 2*x }
  end
end

>> [1, 2, 3].double { |x| puts(x) }
2
4
6 
>> ys = [1, 2, 3].double.select { |x| x > 3 } 
#=> [4, 6]