如何记住在Ruby中可能返回true,false或nil的方法? [英] How can I memoize a method that may return true, false, or nil in Ruby?

查看:120
本文介绍了如何记住在Ruby中可能返回true,false或nil的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

显然||=无法正常工作

def x?
  @x_query ||= expensive_way_to_calculate_x
end

因为如果结果是falsenil,那么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,当解析器命中=时,解析器不会对其进行定义.无论如何,我认为使用orunless的长块形式而不是将unlessdefined?保持一致的习惯是一个好习惯.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆