论坛首页 编程语言技术论坛

方括号感想

浏览 3529 次
锁定老帖子 主题:方括号感想
精华帖 (0) :: 良好帖 (7) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-06-10   最后修改:2009-06-10
Ruby 调用 proc 方式也有很多,如:
p.call a, b
p.(a, b)
p.[] a, b
p[a, b]


其中,方括号语法的接口和 Hash 相同。原因用一句话表达: 函数是一种映射(Map)

Hash 映射和 Proc 映射区别在于: Hash 带有缓存机制,而 Proc 不缓存结果

将 Proc 改造成带缓存的映射,只需要:
Hash.new {|h, k| h[k] = p[k]}


为使代码更易懂,改造一下 Proc,增加 memoise 方法:
class Proc
  def memoise
    Hash.new {|h, k| h[k] = self[k]}
  end
end


使缓存失效,用 Hash 的内置函数就够了,例如:
p = proc {|x| x*2}.memoise
p[3]
# => 6
p[4]
# => 8
p
# => {3=>6,4=>8}
p.delete 3  # 删除这个 key 对应的缓存
p
# => {4=>8}
p.clear     # 删除所有缓存
p
# => {}


这种缓存方式的缺点是 Proc 只允许一个参数,希望以后能改善一下 Hash.new 和 Hash.[] 的写法 ……

对于多进程的应用,这个缓存方式查找比全局缓存略快,但命中率低,也没法通知别的进程缓存失效(有是有,不过就失去简单性,变成 cache 框架了……)。

如果 Proc 是 pure 函数,如 route helper,这个缓存方式就很方便。
   发表时间:2009-06-10   最后修改:2009-06-10
那要不要给memoize生成的Hash加个call方法让它跟Proc更像?顺便把arity还是啥的属性设成1 toka
0 请登录后投票
   发表时间:2009-06-10   最后修改:2009-06-10
…… 好吧,继续改造:

class Proc
  module ProcLike
    def call x; self[x]; end  # 有了 call 自动产生 .() 方法
    def arity; 1; end
    def is_a? klass; klass == Proc; end
    alias kind_of? is_a?
    def class; Proc; end
    def inspect; "#<Proc:0x#{object_id.to_s 16}@memoize>"; end
  end

  def memoize
    hsh = Hash.new {|h, k| h[k] = self[k]}
    hsh.__send__ :extend, ProcLike
    hsh
  end
end


似乎挺完美,但是没完呢,还得盖掉 Hash 的很多东西……

不如换个思路:
class Proc
  module Memoized
    def [] x  # 嗯,这样可选择性更强,用 call 不 memoize,用 [] 就 memoize
      @mem[x] || (@mem[x] = call x)
    end
    def invalidate x
      @mem.delete x
    end
    def clear_cache
      @mem = {}
    end
    def memoized?
      true
    end
  end

  def memoize
    @mem = {}
    self.__send__ :extend, Memoized
    self
  end
  def memoized?
    false
  end
end
0 请登录后投票
   发表时间:2009-06-10  
为了通用实用嘛。像C#的话,之前看到Bart de Smet用Expression Tree来模拟memoization和currying,效果就不错。Expression Tree编译出来的delegate就跟普通的看起来一样。

P.S. s还是z其实问题不大……只是我见过的写法都是z的多。
0 请登录后投票
   发表时间:2009-06-10  
RednaxelaFX 写道
为了通用实用嘛。像C#的话,之前看到Bart de Smet用Expression Tree来模拟memoization和currying,效果就不错。Expression Tree编译出来的delegate就跟普通的看起来一样。

P.S. s还是z其实问题不大……只是我见过的写法都是z的多。


嗯…… 如果 s 用多了,也就成了通假字 ……
0 请登录后投票
   发表时间:2009-06-29  
class Proc  
  module Memoized   
    def [] x, *arg    # 嗯,这样可选择性更强,用 call 不 memoize,用 [] 就 memoize   
      yy = arg.length == 0 ? x : [x, arg].flatten
      @mem[sol_arg(x, arg)] || (@mem[sol_arg(x, arg)] = call x, arg)   
    end  

    def invalidate x, *arg   
      @mem.delete sol_arg(x, arg)   
    end  

    def clear_cache   
      @mem = {}   
    end  

    def memoized?   
      true  
    end  

    private
    def sol_arg x, arg
      arg.length == 0 ? x : [x, arg].flatten
    end
  end  
  
  def memoize   
    @mem = {}   
    self.__send__ :extend, Memoized   
    self  
  end  

  def memoized?   
    false  
  end  
end  

 借楼主思路继续改进以支持多参(多参的情况还是占多数)。

0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics