gpt4 book ai didi

升级到 Ruby 2.0.0p648 后,Ruby "once"方法不再有效

转载 作者:太空宇宙 更新时间:2023-11-03 16:16:26 24 4
gpt4 key购买 nike

我有一些昂贵的子程序,如果多次调用它们,可能会导致进程运行需要很长时间才能完成。

为了阻止它们被重复调用,我们创建了一个类似于 date.rb 中的 Once 模块:

module Once
# modify a method to run only once
def once(*ids) # :nodoc:
ids.each do |id|
module_eval <<-"end;"
alias_method :__#{id.to_i}__, :#{id.to_s}
private :__#{id.to_i}__
def #{id.to_s}(*args, &block)
(@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0]
end
end;
end
end

end

它是这样使用的:

def expensive_function
blah, blah
end
once :expensive_function

这在 Ruby 1.8.6 中运行良好,但现在,在我升级到 Ruby 2.0.0p648 后,出现以下错误:

:in `block in once': undefined method `to_i' for :log_level_from_env:Symbol (NoMethodError)

此错误引用了包含 alias_method 的行号。

需要做哪些修改才能更正此模块,以便它可以根据需要与我当前的 Ruby 版本一起使用?

最佳答案

首先要注意的是,自 ruby​​ 2.0 def method_name; end 返回 :method_name 符号所以你可以这样写

once def method_name
...
end

这是在 ruby​​ 2.3.3 中同样工作的工作片段

module Once
# modify a method to run only once
def once(*method_names) # :nodoc:
method_names.each do |method_name|
module_eval <<~RUBY
alias_method :__#{method_name.to_s}__, :#{method_name.to_s}

private :__#{method_name.to_s}__

def #{method_name.to_s}(*args, &block)
(@__#{method_name.to_s}__ ||= [__#{method_name.to_s}__(*args, &block)])[0]
end
RUBY
end
end
end

class FooBar
extend Once

once def test
puts 'FooBar'
end
end

foo_bar = FooBar.new
100.times do
foo_bar.test
end

P. S.

还有一个很好的 gem,它是为同样的目的而创建的 memoizer ,也许你会发现它很有用

关于升级到 Ruby 2.0.0p648 后,Ruby "once"方法不再有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43352531/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com