Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 基于Ruby枚举器的延迟展平方法_Ruby On Rails_Ruby_Functional Programming_Lazy Evaluation_Enumerator - Fatal编程技术网

Ruby on rails 基于Ruby枚举器的延迟展平方法

Ruby on rails 基于Ruby枚举器的延迟展平方法,ruby-on-rails,ruby,functional-programming,lazy-evaluation,enumerator,Ruby On Rails,Ruby,Functional Programming,Lazy Evaluation,Enumerator,Michael Harrison在上发表了一篇很好的文章,提供了lazy\u select和lazy\u map的实现。我想知道lazy_flant的以下实现是否应该对枚举器和可枚举类型以外的任何类型进行特殊处理 class Enumerator def lazy_flatten Enumerator.new do |yielder| self.each do |value| if value.kind_of? Enumerator

Michael Harrison在上发表了一篇很好的文章,提供了
lazy\u select
lazy\u map
的实现。我想知道
lazy_flant
的以下实现是否应该对
枚举器和
可枚举类型以外的任何类型进行特殊处理

class Enumerator

  def lazy_flatten
    Enumerator.new do |yielder|
      self.each do |value|
        if value.kind_of? Enumerator
          value.lazy_flatten.each do |v|
            yielder.yield v
          end
        elsif value.kind_of? Enumerable
          value.flatten.each do |v|
            yielder.yield v
          end
        else
          yielder.yield value
        end
      end
    end
  end

end
  • 在我看来,这并不懒惰,因为您仍然在下面执行旧的(非懒惰的)
    flatten
  • 枚举器
    可枚举的
    ,因此我认为您不需要单独处理它
  • 我希望
    lazy\u flant
    Enumerable
    上的方法
  • 以下是我将如何实施它:

    module Enumerable
      def lazy_flatten
        Enumerator.new do |yielder|
          each do |element|
            if element.is_a? Enumerable
              element.lazy_flatten.each do |e|
                yielder.yield(e)
              end
            else
              yielder.yield(element)
            end
          end
        end
      end
    end
    

    注意,在Ruby 2.0+中,您不需要这样做,只需使用,它返回一个

    出于我不清楚的原因,
    Lazy
    没有
    flatten
    ,但它有,所以原则上你可以使用
    flatte\u map

    模块可枚举
    def lazy_展平
    self.lazy.flat_映射{| x | x}
    结束
    结束
    
    Lazy#flat_map
    主要负责分解任何可分解元素,但不完全是从以下方面:

    如果以下任一条件为真,则分解块返回的值x:

  • x同时响应
    每个
    强制
    ,这意味着
    x
    是一个惰性枚举器
  • x是一个数组或响应
    到_ary
  • 请注意,
    到_ary
    不是可枚举的
    方法,可能是为了阻止从无限序列到数组。这意味着,例如,如果您试图用上述代码展平包含
    集合
    范围
    的对象,则它(arguaby,见下文)将不起作用:

    a=[[1,2,3],Set[4,5],6,7..8]
    # => [[1, 2, 3], #, 6, 7..8] 
    f=a.lazy\u展平
    # => #  
    f、 到
    # => [1, 2, 3, #, 6, 7..8]
    
    但是,这与
    数组#展平
    的行为相同:

    a.flatten
    # => [1, 2, 3, #, 6, 7..8]
    
    (虽然
    Array#flant
    不会检测和分解惰性枚举数,
    lazy#flat(map
    会检测和分解惰性枚举数。)

    而OP的代码或中的代码将分解
    集合
    范围

    f=a.lazy\u flatten(M.J.的代码)
    # => #
    f、 到
    # => [1, 2, 3, 4, 5, 6, 7, 8]
    
    但是,如果传递包含无限序列的内容,该代码也将无限迭代:

    a=[[1,2,3],Set[4,5],6,7..8,9..Float::INFINITY]
    #=>[[1,2,3],#,6,7..8,9..无穷大]
    f=a.lazy_flatten(M.J.的代码)
    # => #
    f、 到
    #=>在100%CPU下旋转一段时间,最终耗尽内存
    

    如果你认为这是一个特性,而不是一个bug,那么一种方法是修改<代码>平面地图> /COD>基础实现,将它找到的任何枚举都转换成懒惰的:

    模块可枚举
    def lazy_展平
    self.lazy.flat|map do|x|
    x、 对(懒惰)有反应吗?x、 懒惰:x
    结束
    结束
    结束
    
    这甚至适用于嵌套的惰性枚举,因为
    lazy#lazy
    足够聪明,可以返回自身