2014-07-23 82 views
0

我通常用“一次分配”(真的不知道怎么称呼这个ANW)的红宝石这样的:红宝石一次分配变量

class FooBar 
    def foo 
     @foo ||= begin 
      # Costly operation putting here 
     end 
    end 
end 

这将允许可变@foo是只计算一次,然后在方法foo的后续调用中直接使用。我的问题是:

  1. 是使用begin/end块在这种情况下,好还是不好,因为文档指出它是用于封装例外,没有提到任何其他用途。
  2. 我可以使用其他的块类型(Proc,Lambda,do/end)吗?如果是,那么如何?
+0

http://en.wikipedia.org/wiki/Memoization – bjhaid

+0

这是正常的'initialize'完成,但可以在任何地方进行。是的,'@ foo'可以指向任何类型操作的结果:'@foo = arr.map ...','@foo = if..else ... end','@foo = lambda .. .'等 –

+1

一旦给出了评论或答案,请不要更改您的代码,因为它可能会使后者变得毫无意义。最好将它保持原样并添加一个注释(作为编辑,而不是注释),解释您的意图,最好使用单词“编辑”,例如“编辑:...”。 –

回答

2
  1. 我还没有在背诵中看到begin/end的任何用法,但我认为那很好。

  2. 当然,你可以使用lambda这样@foo ||= lambda { "foo" }.call,只记得一次分配||=)只有当@foo进行评估,以false评估PROC。它等同于以下内容:

    if @foo 
        @foo 
    else 
        @foo = lambda { "foo" }.call 
    end 
    
+0

但是这并不意味着我必须使用'@ foo.call'来获取'@ foo'的值吗? – herophuong

+0

@herophuong是的,你需要手动做到这一点。 –

+0

@herophuong我已经更新了我的答案。 –

1

我通常做这样的事情:

class MyClass 

    def foo 
    @foo ||= build_foo 
    end 

    private 

    def build_foo 
    puts "I'm expensive" 
    5 
    end 

end 

我不明白你为什么会需要做任何比较复杂。在我看来,有一种名为build_XXXprocess_XXX的方法清楚地解释了它正在做更多的事情,并且通过公开访问的方法进行记忆,这清楚地表明,如果需要,您可以避免多次执行此操作。

+0

我们不知道herophuong是否多次调用'foo'。它可以被调用一次(与'initialize'一样),然后使用'@ foo'调用其他方法。 –

+0

是的,这是一个错字,我更新了这个问题 – herophuong