【问题标题】:ruby methods that either yield or return Enumerator产生或返回 Enumerator 的 ruby​​ 方法
【发布时间】:2011-11-03 05:52:24
【问题描述】:

在最新版本的 Ruby 中,Enumerable 中的许多方法在没有块的情况下被调用时返回 Enumerator

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

我想用我自己的方法做同样的事情,像这样:

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 }

【问题讨论】:

    标签: ruby enumerable


    【解决方案1】:

    核心库插入一个保护return to_enum(:name_of_this_method, arg1, arg2, ..., argn) unless block_given?。在你的情况下:

    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]
    

    【讨论】:

    • 整洁。不知道这个。
    • 小注:有时你的函数需要接受参数,所以使用to_enum:my_method 是行不通的(因为当枚举可枚举时,你的函数将在没有参数的情况下被调用)。例如,如果这里的示例是 def mult_by(factor) ... end,则需要使用 to_enum(:my_method, factor)
    【解决方案2】:

    使用Enumerator#new:

    class Array
      def double(&block)
        Enumerator.new do |y| 
          each do |x| 
            y.yield x*2 
          end 
        end.each(&block)
      end
    end
    

    【讨论】:

    • 谢谢 - .each(&amp;block) 的使用正是我想要的
    【解决方案3】:

    另一种方法可能是:

    class Array
        def double(&block)
            map {|y| y*2 }.each(&block)
        end
     end
    

    【讨论】:

    • 这就是它的精髓,但与@levinalex 的回答相比,此解决方案在任何消费者调用之前在整个数组中运行地图。
    【解决方案4】:

    对我来说最简单的方法

    class Array
      def iter
          @lam = lambda {|e| puts e*3}
          each &@lam
      end
    end
    
    array = [1,2,3,4,5,6,7]
    array.iter
    

    => 3 6 9 12 15 18 21

    【讨论】:

      猜你喜欢
      • 2014-12-21
      • 2012-02-21
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 2021-05-17
      • 1970-01-01
      相关资源
      最近更新 更多