如何在Ruby中记忆可能返回true,false或nil的方法?

显然||=不会起作用

 def x? @x_query ||= expensive_way_to_calculate_x end 

因为如果结果是falsenil ,那么expensive_way_to_calculate_x就会反复运行。

目前我知道的最好方法是将值放入Array

 def x? return @x_query.first if @x_query.is_a?(Array) @x_query = [expensive_way_to_calculate_x] @x_query.first end 

有更传统或更有效的方法吗?

更新我意识到我想记住除了false nil之外 – 这一直回到https://rails.lighthouseapp.com/projects/8994/tickets/1830-railscachefetch-does-not-work-with-false -boolean-as-cached-value – 我对Andrew Marshall道歉,他给出了一个完全正确的答案。

明确检查@x_query的值@x_querynil

 def x? @x_query = expensive_way_to_calculate_x if @x_query.nil? @x_query end 

请注意,如果这不是实例变量,则必须检查它是否也被定义,因为所有实例变量都默认为nil

鉴于您的更新, @x_query的memoized值可以为nil ,您可以使用已defined? 而是绕过所有实例变量默认为nil的事实:

 def x? defined?(@x_query) or @x_query = expensive_way_to_calculate_x @x_query end 

注意, a = 42 unless defined?(a)类似a = 42 unless defined?(a)东西a = 42 unless defined?(a)将无法按预期工作,因为一旦解析器命中a =a就会达到条件之前定义。 但是,实例变量不是这样,因为它们默认为nil ,当它命中=时,解析器不会定义它们。 无论如何,我认为这是一个很好的习惯用法,或者unlessdefined? unless使用长块forms而不是单行formsdefined? 保持一致。

为了占nil ,使用defined? 查看变量是否已定义:

 def x? return @x_query if defined? @x_query @x_query = expensive_way_to_calculate_x end 

defined? 如果尚未定义变量,则返回nil否则返回字符串"instance_variable"

 irb(main):001:0> defined? @x => nil irb(main):002:0> @x = 3 => 3 irb(main):003:0> defined? @x => "instance-variable"