我编写了一个脚本,其中包含一些方法定义,没有类和一些公共代码。其中一些方法执行一些非常耗时的shell程序。但是,这些shell程序只需在第一次调用方法时执行。
现在在C中,我会在每个方法中声明一个静态变量,以确保这些程序只执行一次。我怎么能用Ruby做到这一点?
答案 0 :(得分:10)
红宝石中有一个成语:x ||= y
。
def something
@something ||= calculate_something
end
private
def calculate_something
# some long process
end
但是如果你的'长时间运行的实用程序'可能返回错误值(false或nil),这个习惯用法就会出现问题,因为||=
运算符仍会导致右侧被评估。
如果您期望错误的值,那么使用另一个变量,方式类似于DigitalRoss提出的方法:
def something
return @something if @something_calculated
@something = calculate_something
@something_calculated = true
return @something
end
首先设置@something_calculated变量,然后运行calculate_something,不要尝试保存一行代码。如果您的计算函数引发异常,则您的函数将始终返回nil并且永远不会再次调用计算。
更一般地说,在Ruby中使用实例变量。但请注意,它们在给定对象的所有方法中都是可见的 - 它们不是方法的本地方法。
如果需要所有实例共享的变量,请在类对象中定义方法,并在每个实例中调用self.class.something
class User
def self.something
@something ||= calculate_something
end
def self.calculate_something
# ....
end
def something
self.class.something
end
end
答案 1 :(得分:4)
“memoize”宝石可能在这里很好。当你记住一个方法时,它只被调用一次:
require 'memoize'
include Memoize
def thing_that_should_happen_once
puts "foo"
end
memoize :thing_that_should_happen_once
thing_that_should_happen_once # => foo
thing_that_should_happen_once # =>
答案 2 :(得分:1)
def f
system "echo hello" unless @justonce
@justonce = true
end
而且,嗯,如果你想让它在调用上运行一个shell命令,直到它成功,你可能会尝试:
def f x
@justonce = system x unless @justonce
end
答案 3 :(得分:1)
def my_time_consuming_method
@result ||= begin
sleep 5
true
end
end
my_time_consuming_method # true after 5 secs
my_time_consuming_method # true directly
答案 4 :(得分:1)
与此线程中的其他解决方案不同,此解决方案不要求您保持任何状态:
获取调用后删除自身的方法或使用空方法覆盖自身:
def hello
puts "hello"
define_singleton_method(:hello) {}
end
OR:
def hello
puts "hello"
singleton_class.send(:undef_method, __method__)
end
答案 5 :(得分:0)
确保shell命令只运行一次是一种重复出现的模式。我编写的一个解决方案是对命令行上的输入文件进行校验和,并且只在shell命令之前没有运行时才执行它。当输入文件发生变化时,它也会再次执行。参见
https://github.com/pjotrp/once-only
只需在shell命令中加上'once-only'即可使用它。 E.g。
bowtie -t e_coli reads/e_coli_1000.fq e_coli.map
变为
once-only bowtie -t e_coli reads/e_coli_1000.fq e_coli.map
对于PBS添加--pbs开关。