【问题标题】:lambda's method? Mats' example code confuse me .lambda的方法? Mats 的示例代码让我感到困惑。
【发布时间】:2012-08-13 08:12:15
【问题描述】:
def memoize
  cache = {}
  lambda { |*args| 
    unless cache.has_key?(args)
      cache[args] = self[*args]
    end
    cache [args]
  }
end

factorial =  lambda {|x| return 1 if x== 0; x*factorial[x-1];}.memoize

puts factorial.call 10

代码来自《红宝石编程语言》一书。 但这让我很困惑:method(memoize) 如何将 lambda 作为它的方法应用? lambda 可以跟其他 lambda 以 dot(.) 作为自己的方法吗?

lambda {|x| return 1 if x== 0; x*factorial[x-1];}.memoize

顺便说一句:上面的代码在 irb 中工作,但是 ruby​​ 解释器遇到如下错误:

memoize.rb:11: private method `memoize' called for #<Proc:0x0000000103bba018@memoize.rb:11> (NoMethodError)

为什么?

【问题讨论】:

    标签: ruby methods lambda


    【解决方案1】:

    你在哪里说这个:

    def memoize
      #...
    end
    

    我想你的意思是这样的:

    class Proc
      def memoize
        #...
      end
    end
    

    这将向 Procs 添加一个公共 memoize 方法,而 lambda { ... }(或较新的 Rubies 中的 -&gt; { ... })为您提供一个 Proc 实例。

    现在转到memoize 本身。方法返回它们最后一个表达式的值,对于memoize,最后一个表达式是这样的:

    lambda { |*args| 
      unless cache.has_key?(args)
        cache[args] = self[*args]
      end
      cache [args]
    }
    

    所以memoize 为 Proc (self) 返回一个包装器,它是 cache 的一个闭包,而这个包装器所做的只是:

    1. 检查cache 是否有相关参数列表的条目(数组args)。
    2. 如果我们没有缓存值,则计算原始 Proc 的值 (self[*args]) 并将其存储在缓存中。
    3. 返回缓存值。

    您可以使用[] 方法执行Proc,因此proc.call(a, b)proc[a, b] 相同。

    【讨论】:

      【解决方案2】:

      顶层的对象是main,在那里定义的任何方法都作为私有实例方法添加到Object(因此它们在任何地方都可用)。

      为什么它在 irb 会话中起作用?因为context mode(也是here),在irb中默认是3。使用例如值 0 (irb --context-mode 0),现在它们将像往常一样作为私有方法添加。

      如果 sn-p 显式定义要修改的类而不是使用隐式顶层,那么出于教学目的可能会更可取。

      【讨论】:

      • Private Object 的实例方法,不是吗?因此,特定的错误消息(我也在 irb 中看到)。
      • @mu:是的,作为私人,添加到答案中。问题是,至少对于 irb 1.9.3p125,它会将其添加为公共。
      猜你喜欢
      • 2013-08-28
      • 2017-01-03
      • 1970-01-01
      • 2017-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多