听懒惰的数字

时间:2016-06-03 11:16:25

标签: ruby lazy-evaluation enumerable

我正在尝试构建一些可以处理事件流的东西。我希望我的处理器没有副作用,因此它们易于管理,但我也想确保我不会两次运行流。

class A
  def initialize(*processors)
    @processors = processors
  end
  def call(list)
    @processors.inject(0) { |acc, p|
      acc + p.call(list)
    }
  end
end

class B
  def initialize(multiplier)
    @multiplier = multiplier
  end

  def call(list)
    list.map { |i|
      i * @multiplier
    }.inject(0) { |acc, i|
      puts "B with multipler: #{@multiplier}, adding: #{i}"
      acc + i
    }
  end
end

A.new(B.new(1), B.new(2)).call([1, 2, 3, 4, 5].lazy)
# => 45

A完全错误,因为执行顺序是:

# B with multipler: 1, adding: 1
# B with multipler: 1, adding: 2
# B with multipler: 1, adding: 3
# B with multipler: 1, adding: 4
# B with multipler: 1, adding: 5
# B with multipler: 2, adding: 2
# B with multipler: 2, adding: 4
# B with multipler: 2, adding: 6
# B with multipler: 2, adding: 8
# B with multipler: 2, adding: 10

我怎样才能修改A类给我一个执行顺序:

# B with multipler: 1, adding: 1
# B with multipler: 2, adding: 2
# B with multipler: 1, adding: 2
# B with multipler: 2, adding: 4
# B with multipler: 1, adding: 3
# B with multipler: 2, adding: 6
# B with multipler: 1, adding: 4
# B with multipler: 2, adding: 8
# B with multipler: 1, adding: 5
# B with multipler: 2, adding: 10

我是否需要某种更复杂的可枚举类型?

1 个答案:

答案 0 :(得分:0)

如果要将处理器应用于值,则需要一次发送一个

class A
  def initialize(*processors)
    @processors = processors
  end
  def call(list)
    list.inject(0) do |acc, item|
      acc + @processors.map { |processor| processor.call(item) }.inject(:+)
    end
  end
end

class B
  def initialize(multiplier)
    @multiplier = multiplier
  end

  def call(item)
    puts "B with multipler: #{@multiplier}, adding: #{item}"
    item * @multiplier
  end
end

p A.new(B.new(1), B.new(2)).call([1, 2, 3, 4, 5].lazy)