能否将yield_self特性反向移植到Ruby 2.5以下版本?
解决方案
完全可以在Ruby 2.5之前的版本反向移植yield_self。该方法的核心逻辑非常简单:将方法接收者作为参数传入关联的块执行,最终返回块的执行结果,只需要给核心类加极小的补丁就能和2.5+原生实现行为完全对齐。
补丁实现
把下面的代码加到应用的初始化入口位置即可:如果是Rails项目,放到config/initializers/目录下新建的monkey patch文件里;如果是纯Ruby脚本,放到脚本执行逻辑的最开头。
class Object def yield_self return to_enum(:yield_self) unless block_given? yield self end end
补丁兼容Ruby 1.9.3及以上所有2.5之前的版本,无额外依赖。
兼容性说明
- 补丁打完后你提供的示例代码可以直接无修改运行,和高版本Ruby的执行结果完全一致:
"data.csv" .yield_self { |name| File.expand_path(name, __dir__) } .yield_self { |path| File.read(path) } .yield_self { |body| CSV.parse(body) } .map { |row| row[1].to_i } .sum - 补丁完全对齐原生行为:未传块调用时会返回对应枚举器,支持链式调用
Enumerator的所有方法(比如with_index),不会出现行为偏差。 - 后续如果升级Ruby到2.5及以上版本,该补丁不会和原生实现冲突,Ruby会自动优先加载原生方法,不需要手动删除补丁代码,版本升级无感知。
- 补丁不会侵入其他核心方法逻辑,不会和现有业务代码产生命名冲突。
内容的提问来源于stack exchange,提问作者Nikita Fedyashev
相关产品推荐
相关产品推荐

