7
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

コードは本「Ruby プログラミング言語」からのものです。しかし、それは私を混乱させます:メソッド(メモ化)をそのメソッドとしてラムダにどのように適用できますか? 独自のメソッドとして 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)

なんで?

4

2 に答える 2

7

あなたがこれを言っているところ:

def memoize
  #...
end

私はあなたがこれを言うつもりだと思います:

class Proc
  def memoize
    #...
  end
end

これにより、パブリックmemoizeメソッドが Procs に追加され、 lambda { ... }(または-> { ... }新しい Ruby では) Proc インスタンスが提供されます。

次に、memoizeそれ自体に進みます。メソッドは最後の式の値を返します。 for のmemoize場合、最後の式は次のとおりです。

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

したがって、クロージャーであるmemoizeProc ( ) のラッパーを返します。このラッパーが行うことは次のとおりです。selfcache

  1. cache問題の引数リスト ( Array ) のエントリがあるかどうかを確認しますargs
  2. キャッシュされた値がない場合は、元の Proc の値 ( self[*args]) を計算し、キャッシュに格納します。
  3. キャッシュされた値を返します。

メソッドを使用し[]て Proc を実行できるのでproc.call(a, b)、 と同じproc[a, b]です。

于 2012-08-13T08:28:42.967 に答える
4

最上位のオブジェクトはmainで、そこに定義されたメソッドはプライベート インスタンス メソッドとして追加されますObject(したがって、どこでも使用できます)。

irb セッション内で機能するのはなぜですか? これは、irb のデフォルトで3であるコンテキスト モード(ここでも)のためです。たとえば、値0 ( ) を使用すると、通常どおりプライベート メソッドとして追加されます。irb --context-mode 0

暗黙のトップレベルを使用する代わりに、スニペットがどのクラスが変更されているかを明示的に定義した方が、教育目的にはおそらく好ましいでしょう。

于 2012-08-13T08:30:01.770 に答える