翻译 Hash and default_proc

alex_marmot · 2015年06月05日 · 2032 次阅读

原文地址:http://thingsinabucket.com/2015/05/27/hash_default_proc/?utm_source=rubyweekly&utm_medium=email Ruby 新手渣翻,翻得不好,烦请指正。

Hash and default_proc

Hash#default_proc 是我最喜欢的 Ruby 特性之一。让我们看看它能做些什么。 有没有见过这样的代码? ###

    result = {}
    some_collection.map do |some_entry|
      result[some_entry] = some_expensive_operation(some_entry)
    end
    result

不要这样写了

除非集合中所有的值都会被使用不然这花费不菲的计算应该被推迟到需要它的时才进行

    result = Hash.new do |hash, key|
     hash[key] = some_expensive_operation(key)
    end

这代码现在看起来好多了

当找不到键的时候Ruby将会对 Block 中的代码进行求值这使它成为在进行这类键值查找或者快速缓存
时极好的工具

在上期的文章中我们知道了能通过方括号来调用Proc当这样的操作开销太大时只需用一个Hash来包裹
它们

    expensive_proc = ->(v) do
      puts "Expensive calculation"
      sleep 1
      [v] * 2
    end

    expensive_proc_with_cache = Hash.new do |hash, value|
      hash[value] = expensive_proc[value]
    end

    def repeat_10_times(proc)
      10.times do |i|
        proc[ i % 2 ]
      end
    end

    repeat_10_times(expensive_proc) # 花费了10秒
    repeat_10_times(expensive_proc_with_cache) # 花费了2秒

这是个巨大的改善

当你调用 API 它一同返回了前一个与后一个的值怎么样?不用就太浪费了吧~

    paginated_lookup = ->(index) do
      v = "index[#{index}]"
      {
        index => v,
        (index + 1) => v + '.next',
        (index - 1) => v + '.prev',
      }
    end

    paginated_lookup_cache = Hash.new do |hash, key|
      hash.merge! paginated_lookup[key]
      hash[key]
    end

    paginated_lookup_cache[10] # => "index[10]"
    paginated_lookup_cache[11] # => "index[10].next"

警告
在调用 Hash#fetch 时,Hash#default_proc将不会被调用。作者很是震惊~!

    times2 = Hash.new { |_, v| v*2} # => {}
    times2.fetch(1) # KeyError: key not found: 1

请也不要使用这种"变通"方案

    times2.fetch(1) { |k| times2[k] }

这只是一坨翔~~~
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号