c - 任何人都可以提供有关猴子修补/挂钩 Ruby 的字符串 #{} 以进行插值的指导吗?
问题描述
我正在对 Ruby 语言的一些核心组件进行monkeypatching(我知道,我知道,monkeypatching 很糟糕) - 我特别需要做的是挂钩:
"#{some_variable}"
我天真的方法是用 whitequark 解析器 gem 解析 AST 并将所有 #{} 重写为 concats(这确实有效),但我不喜欢这条路线的一些要求(猴子修补了很多其他东西来获得每一个加载文件[问题列表继续])。
我已经深入研究了 ruby C 代码,但无法找到实际执行插值的函数。谁能帮我确定该行为的定义位置/方式?
编辑:我想要达到的目标,就像你可以做的那样:
class String
alias_method :my_+, :+
def +(other)
puts 'patched'
self.my_+(other)
end
end
a = "a"
a + "b" => #would output patched
我想要一种类似的方式来修补#{} - 但是,这不能通过正常的猴子修补来完成 - 我正在寻找关于如何在不重写 VM 中每个类的 AST 的情况下实现这一点的一般指导。
解决方案
"str1 #{funcall} str2"
在 Ruby 中执行以下操作:
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,24)>=================
0000 putobject "str1 " ( 1)[Li]
0002 putself
0003 opt_send_without_block <callinfo!mid:funcall, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 dup
0007 branchiftype T_STRING, 15
0010 dup
0011 opt_send_without_block <callinfo!mid:to_s, argc:0, FCALL|ARGS_SIMPLE>, <callcache>
0014 tostring
0015 putobject " str2"
0017 concatstrings 3
0019 leave
有很多操作(如果不是字符串,则将 #{} 内容转换为字符串)并使用 concatstrings 命令完成,该命令根据以下内容:http: //lifegoo.pluskid.org/upload/doc/yarv/yarv_iset.html #detail-19调用rb_str_append
换句话说,您不能使用 Ruby 进行修补/挂钩 #{},但正如 cremno 所建议的,您应该查看 C 部分以通过使用自己的挂钩重新编译 Ruby 来覆盖 #{ } 的默认行为。
推荐阅读
- c++ - 在成员函数中创建 Intellisense 列表成员变量,而无需键入“this”
- arrays - (N+1) x 13 数组的 VHDL 移位数组元素
- python-3.x - 在 PyCharm 上导入 Kivy 时出现错误“[Core] 选项 --mode 无法识别”
- autodesk-forge - Autodesk Forge:如何在 BIM 360 Docs 中查找模型的 svf 文件的 URL
- java - 如何从 SpringBoot 应用程序连接到 Azure keyvault 以使用 MSI 进行本地开发
- python - 如何修复:“在 sql 'SELECT * FROM Country' 上执行失败:没有这样的表:国家”
- java - 使用 Spring MVC 和 Kotlin,为什么忽略这个 Body?
- c++ - 可以比较两个指向成员函数的指针是否相等吗?
- responsive - 如何防止电子邮件客户端像 putsmail 那样删除媒体查询?
- share - 在核心 php 中如何在社交媒体上分享产品标题、图片和描述?