如何记住在Ruby中可能返回true,false或nil的方法? [英] How can I memoize a method that may return true, false, or nil in Ruby?
问题描述
显然||=
无法正常工作
def x?
@x_query ||= expensive_way_to_calculate_x
end
因为如果结果是false
或nil
,那么expensive_way_to_calculate_x
将会一遍又一遍地运行.
because if it turns out to be false
or nil
, then expensive_way_to_calculate_x
will get run over and over.
目前,我所知道的最好方法是将值放入Array
:
Currently the best way I know is to put the value into an Array
:
def x?
return @x_query.first if @x_query.is_a?(Array)
@x_query = [expensive_way_to_calculate_x]
@x_query.first
end
是否有更常规或更有效的方法?
Is there a more conventional or efficient way of doing this?
更新我意识到除了false
之外我还想记住nil
-这一直追溯到安德鲁·马歇尔(Andrew Marshall)给出了完全正确的答案.
UPDATE I realized that I wanted to memoize nil
in addition to false
- this goes all the way back to https://rails.lighthouseapp.com/projects/8994/tickets/1830-railscachefetch-does-not-work-with-false-boolean-as-cached-value - my apologies to Andrew Marshall who gave an otherwise completely correct answer.
推荐答案
显式检查@x_query
的值是否为nil
:
def x?
@x_query = expensive_way_to_calculate_x if @x_query.nil?
@x_query
end
请注意,如果这不是实例变量,则由于所有实例变量默认为nil
,因此您必须检查它是否也已定义/代替定义.
Note that if this wasn't an instance variable, you would have to check if it was defined also/instead, since all instance variables default to nil
.
鉴于您将@x_query
的记忆值设置为nil
的更新,可以改用defined?
避开所有实例变量默认为nil
的事实:
Given your update that @x_query
's memoized value can be nil
, you can use defined?
instead to get around the fact that all instance variables default to nil
:
def x?
defined?(@x_query) or @x_query = expensive_way_to_calculate_x
@x_query
end
请注意,执行a = 42 unless defined?(a)
之类的操作将无法按预期方式进行,因为一旦解析器命中a =
,便会在之前将a
定义为 .但是,实例变量并非如此,因为它们默认为nil
,当解析器命中=
时,解析器不会对其进行定义.无论如何,我认为使用or
或unless
的长块形式而不是将unless
与defined?
保持一致的习惯是一个好习惯.
Note that doing something like a = 42 unless defined?(a)
won't work as expected since once the parser hits a =
, a
is defined before it reaches the conditional. However, this isn't true with instance variables since they default to nil
the parser doesn't define them when it hits =
. Regardless, I think it's a good idiom to use or
or unless
's long block form instead of a one-line unless
with defined?
to keep it consistent.
这篇关于如何记住在Ruby中可能返回true,false或nil的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!