ruby - 将 ruby​​ 代码注入(inject)嵌套block

标签 ruby

我反复使用这种模式:

pb= ProgressBar.new("blah_map", wtf.count)
newresult= cache("blah_map") do 
  result.map{ |r| pb.inc; { blah: r[:x] } }
end
pb.finish

pb= ProgressBar.new("blah_group", wtf.count)
newresult= cache("blah_group") do 
  result.group_by{ |r| pb.inc; "#{r[:x]}&#{r[:y]}" }
end
pb.finish

所以我自然希望能够做到

def progress_cache(name, count, &block)
  pb= ProgressBar.new(name, count)
  inject_pb_inc(block) # how??
  # do some caching with yield if cache doesn't exist, don't mind this
  pb.finish
end

并这样使用它:

newresult= progress_cache("lol", result.count) do 
  result.map do |r| 
    # progress_cache magically inserted a pb.inc here for pretty animation!  
    r[:omg] 
  end 
end

问题是,如何将 pb.inc 调用注入(inject)到 Progress_cache block 内的 block (map、group_by 等)中?

编辑:重新表述问题

最佳答案

有几种方法可以实现这一点,并在表达能力方面进行各种权衡:

  1. 将进度条作为 block 参数发送

    def progress_cache(name, count &block)
      pb = ProgressBar.new(name, count)
      result = block.call(pb)
      pb.finish
      result
    end
    

    并像这样使用它

    newresult = progress_cache("lol", result.count) do |pb|
      result.map{|r| pb.inc; r[:omg]}
    end
    
  2. 创建一个新的 map 函数,自动增加进度条(您可以直接覆盖 result.map,或提供 result.map_with_progress,但我会将其留给您)

    def map_with_progress(container, name, &block)
      pb = ProgressBar.new(name, container.count)
      result = container.map{|obj| block.call(obj)}
      pb.finish
      result
    end
    

    然后像这样使用它

    newresult = map_with_progress(result, "lol") { |r| r[:omg] }
    

    当然,由于您同时执行映射和 group_by,因此您必须在此处使用两个辅助方法,这可能会开始变得困惑。

  3. 使用高阶函数

    def function_with_progress(obj, func_name, name, count, &block)
      pb = ProgressBar.new(name, count)
      result = obj.__send__(func_name) do |param|
        pb.inc
        block.call(param)
      end
      pb.finish
      result
    end
    

    然后像这样使用它

    newresult = function_with_progress(result, "map", "lol", result.count) do |r|
      r[:omg]
    end
    

    但我不推荐这种方法,因为它太抽象了。它可以在 javascript 或 clojure 等函数式语言中工作,但我认为它不适合 ruby​​。

关于ruby - 将 ruby​​ 代码注入(inject)嵌套block,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11858799/

相关文章:

Ruby 解析包含文本和图像的 PDF 文件

ruby-on-rails - 这应该在模型中吗?如果是这样,我应该怎么写这个?

java - 你如何在 Java 中使用 Ruby?

ruby-on-rails - 如何在一天结束时将 boolean 值重置为 "default: false"?

ruby-on-rails - Mechanize 和 Capybara 的区别(使用 webmock/webkit/selenium)

ruby - 如何在同一个源文件中拥有测试单元?

ruby-on-rails - 在 Rails 4 中更改临时目录

ruby-on-rails - 如何使用 Ruby/Rails 将购买仅限于美国的 IP 地址?

ruby-on-rails - 如何从句子中删除单词数组?

ruby - 匹配不以 test.js 结尾但以 .js 结尾的文件的正则表达式