我寫了一個包含幾個方法定義,沒有類和一些公共代碼的腳本。其中一些方法執行一些非常耗時的shell程序。但是,這些shell程序只需要在第一次調用該方法時執行。如何在Ruby中只執行一次方法?有靜態變量嗎?
現在在C中,我會在每個方法中聲明一個靜態變量,以確保這些程序只執行一次。我怎麼能在Ruby中做到這一點?
我寫了一個包含幾個方法定義,沒有類和一些公共代碼的腳本。其中一些方法執行一些非常耗時的shell程序。但是,這些shell程序只需要在第一次調用該方法時執行。如何在Ruby中只執行一次方法?有靜態變量嗎?
現在在C中,我會在每個方法中聲明一個靜態變量,以確保這些程序只執行一次。我怎麼能在Ruby中做到這一點?
有紅寶石成語:x ||= y
。
def something
@something ||= calculate_something
end
private
def calculate_something
# some long process
end
但有這個成語一個問題,如果你的「長期運行的程序」可能會返回一個假值(false或無),因爲||=
運營商仍然將導致評估的右側。 如果您希望假值,則使用一個額外的變量,在類似的方式提出DigitalRoss:
def something
return @something if @something_calculated
@something = calculate_something
@something_calculated = true
return @something
end
不要試圖通過先設定@something_calculated變量,然後運行保存一行代碼calculate_something。如果您的計算函數引發異常,您的函數將始終返回零,並且不會再次調用計算。
更一般地說,在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
def f
system "echo hello" unless @justonce
@justonce = true
end
而且,嗯,如果你想讓它在調用運行shell命令,直到它成功,你可以嘗試:
def f x
@justonce = system x unless @justonce
end
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
的「memoize的」寶石會是個不錯這裏。當你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 # =>
不像在此線程的其他解決方案,該解決方案不要求你不放任何狀態:
獲取方法調用之後除去本身或本身帶有一個空方法改寫:
def hello
puts "hello"
define_singleton_method(:hello) {}
end
OR:
def hello
puts "hello"
singleton_class.send(:undef_method, __method__)
end
確保shell命令只運行一次是循環模式。我編寫的一個解決方案是在命令行上對輸入文件進行校驗和,並僅在shell命令未運行之前執行。當輸入文件改變時它也會再次執行。見
https://github.com/pjotrp/once-only
在前面加上「僅一次」的shell命令簡單地使用它。例如。
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開關。
這對我不起作用,因爲我只定義了方法而沒有定義類。但這真的很整潔!我應該把所有東西都包裝在一個班級中,並且每天給它打電話。 – bastibe 2010-11-04 14:22:46
這將爲你工作。如果你沒有定義類,那麼你正在使用某個Object。嘗試'放self.inspect;把self.class.inspect'放在你的腳本中。 – Arsen7 2010-11-04 14:25:48
事實上,在Ruby中,即使您不知道它,也始終處於對象中,並且所有實例變量都在該範圍內可見。 – 2010-11-04 14:41:14