ruby - Ruby 绑定 instance_eval 访问本地变量?
问题描述
处理一些我需要能够通过字符串定义方法和本地变量的功能binding
我认为代码最适合自己,所以这就是我想要完成的事情:
mybind = binding
mybind.eval("a = 5")
mybind.eval("a") #=> 5
a #=> NameError: undefined local variable or method `a'...
# Calling it in global/main scope doesn't find anything, but it's found in the `mybind` scope
mybind.eval("def thing; 3; end")
mybind.eval("thing") #=> 3
thing #=> NameError: undefined local variable or method `thing'...
# Calling it in global/main scope doesn't find anything, but it's found in the `mybind` scope
本质上,我不希望定义的任何方法/变量进入全局范围,但我希望它们在对同一个绑定/eval 的第二次调用中是可调用的。这些将作为字符串出现,因此可调用块也是不可能的。
我试过instance_eval
, class_eval
, eval
, 和instance_exec
instance_eval
instance_eval
几乎是完美的,除非由于某种原因,在下一次调用中无法访问定义的任何本地变量。
我对使用有点陌生binding
,所以如果有明显的我遗漏的东西,请告诉我。否则,如果有人对如何实现这一点有任何想法,即使使用不同的流程,我也会非常感谢任何帮助。
谢谢!
我在 Ruby 2.7.2 上,但如果能提供解决方案,我可以升级。
解决方案
binding
,根据它的设计,无论何时调用它都会获取当前绑定。如果您在全局范围内调用它,您将获得全局绑定。听起来您想要的是用户无法访问的绑定。我们可以轻松地创建其中之一,只需binding
在一个空函数内部调用即可。
def new_binding
binding
end
现在,每次我调用 时new_binding
,我都会得到一个新的范围,它从 Ruby 的标准全局范围的词法继承而来,但没有该对象,其他任何人都无法访问。
irb(main):012:0> new_binding == new_binding
=> false
irb(main):013:0> my_binding = new_binding
=> #<Binding:0x00005562fd103a00>
irb(main):014:0> my_binding.eval("a = 1")
=> 1
irb(main):015:0> my_binding.eval("a")
=> 1
--
发表评论后编辑
new_binding
通过包装一个简单的特征类,我们可以更接近您正在寻找的内容。
def new_binding
class <<Object.new
return binding
end
end
现在您可以定义方法,但您必须使用显式的self
.
new_binding.eval("def self.thing; 3; end")
new_binding.eval("thing")
很可能有一些技巧可以method_added
绕过显式接收器,但无论出于何种原因,它似乎method_added
都不想在特征类上工作。老实说,我可能最终会提出一个关于我自己的新问题,因为这种行为很奇怪。
推荐阅读
- javascript - 在 javascript github 操作中获取修改后的行号
- .net-core - DocuSign .NET SDK - Esign DLL - 处理 DocuSign 配置参数中有关错误的更改:“意外的 PEM 类型”
- javascript - 如何检查用户是否可以接受 DM
- python - 更 Pythonic 的 If-Else-Pass 编写方式
- reactjs - 如何正确地将参数传递给 useCallback() 钩子?
- chatbot - 我们可以在 headful 模式和(或)Selenium Grid 下运行 BotiumCLI-WebdriverIO 吗?如果是,我们如何修改 Botium.json 来实现这一点?
- google-maps-sdk-ios - 谷歌地图崩溃
iOS Swift,-[GMSTileDataCache loadTileForTileCoords:dataVersion:completionHandler:] - android - 服务通知文本使用系统语言
- teradata - Teradata 无法将日期字符串转换为数值
- http - 在 httputil 反向代理中设置请求正文