gpt4 book ai didi

ruby - 将 block 传递给 define_method

转载 作者:数据小太阳 更新时间:2023-10-29 08:26:55 25 4
gpt4 key购买 nike

问题

有一个模式我发现自己经常使用,所以我想把它晒干。我有这样的东西:

class InfoGatherer
def foo
true
end

def people
unless @people
@people = # Long and complex calculation (using foo)
end
@people
end
end

我想把它弄干成这样:

class InfoGatherer
extend AttrCalculator

def foo
true
end

attr_calculator(:people) { # Long and complex calculation (using foo) }
end

为此,我定义了一个模块 AttrCalculator 以扩展到 InfoGatherer。这是我尝试过的:

module AttrCalculator
def attr_calculator(variable_name_symbol)
variable_name = "@#{variable_name_symbol}"

define_method variable_name_symbol do
unless instance_variable_defined?(variable_name)
instance_variable_set(variable_name, block.call)
end
instance_variable_get(variable_name)
end

end
end

不幸的是,当我尝试像 InfoGatherer.new.people 这样简单的东西时,我得到:

NameError: undefined local variable or method `foo' for InfoGatherer:Class

嗯,这很奇怪。为什么 blockInfoGatherer:Class 的范围内运行,而不是它的实例 InfoGatherer.new

研究

我知道我不能使用 yield,因为那样会 try catch 错误的 block ,如 here 所示.我尝试使用 self.instance_exec(block) 代替上面的 block.call,但随后我收到了一个新错误:

LocalJumpError: no block given

嗯?我在 this SO question 中看到同样的错误,但我已经在使用括号表示法,因此那里的答案似乎并不适用。

我也尝试过使用 class_eval,但我不确定如何在字符串中调用 block。这当然行不通:

class_eval("
def #{variable_name_symbol}
unless #{variable_name}
#{variable_name} = #{block.call}
end
#{variable_name}
end
")

最佳答案

该用例称为内存。它可以像这样轻松完成:

def people
@people ||= # Long and complex calculation (using foo)
end

你不应该像现在这样陷入困境。

关于ruby - 将 block 传递给 define_method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27872482/

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