翻译 Hash and default_proc

alex_marmot · June 05, 2015 · 2026 hits

原文地址: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] }

这只是一坨翔~~~
No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.