instance_eval 的块参数 - 已记录?目的?

2023-11-27

刚刚意识到instance_eval yields self作为关联块的参数(1.9.2 版本中的错误除外:http://www.ruby-forum.com/topic/189422)

1.9.3p194 :003 > class C;end
1.9.3p194 :004 > C.new.instance_eval {|*a| a}
 => [#<C:0x00000001f99dd0>] 
1.9.3p194 :005 > 

这是在某处记录/指定的吗?看着ruby-doc:BasicObject,看不到任何提到的块参数。

当它自身总是被定义时,除了一些纯粹的历史原因之外,是否有理由明确地传递它?


我受到这个打击的方式是:

l = lambda {  }
myobj.instance_eval(&l)  # barks

这在 1.8.x 中工作得很好(我猜是因为块数量没有强制执行)。

然后升级到 1.9.2 - 它仍然有效!这是一个奇怪的巧合,因为即使 lambda 块参数是严格执行的(因此它会抱怨没有声明 self 的参数),但是由于上面链接的错误 - self 实际上没有在这个版本中传递。

然后升级到 1.9.3,该错误得到修复,因此它开始抛出参数错误 - 对于较小的版本更改恕我直言,这非常令人惊讶。

因此,一种解决方法是声明参数,或者将 lambda 改为块:

 l = proc {  }
  myobj.instance_eval(&l) # fine

只是想描述完整的故事,以帮助其他人避免像我一样浪费时间 - 直到这被正确记录。


阅读Ruby的源代码,我可以解释的是:

instance_eval正在执行这个:

return specific_eval(argc, argv, klass, self)

依次运行:

 if (rb_block_given_p()) {
     if (argc > 0) {
         rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
     }
     return yield_under(klass, self, Qundef);
 }

你可以看到他们通过Qundef对于 VALUES 参数。

if (values == Qundef) {
    return vm_yield_with_cref(th, 1, &self, cref);
}

在该特定代码行中,他们手动将 argc(参数计数)设置为 1,并将参数设置为“self”。稍后,准备块的代码将块的参数设置为这些参数,因此第一个参数 =“self”,其余参数为零。

设置块参数的代码正在执行以下操作:

   arg0 = argv[0];

   ... bunch of code ...

     else {
         argv[0] = arg0;
     }

     for (i=argc; i<m; i++) {
         argv[i] = Qnil;
     }

导致:

1.9.3p194 :006 > instance_eval do |x, y, z, a, b, c, d| x.class end
 => Object 
1.9.3p194 :008 > instance_eval do |x, y, z, a, b, c, d| y.class end
 => NilClass 

为什么 ?我不知道,但代码似乎是故意的。很高兴向实施者提出问题,看看他们对此有何评论。

[Edit]

这可能是这样的,因为您传递给 instance_eval 的块可能会或可能不会为其制作(代码取决于将 self 设置为您想要块修改的类),相反,它们可能会假设您将向它们传递您希望它们作为参数进行修改的实例,这样它们也可以与 instance_eval 一起使用。

irb(main):001:0> blk = Proc.new do |x| x.class end
#<Proc:0x007fd2018447b8@(irb):1>
irb(main):002:0> blk.call
NilClass
irb(main):003:0> instance_eval &blk
Object

当然这只是一个理论,没有官方文档我只能猜测。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

instance_eval 的块参数 - 已记录?目的? 的相关文章

  • 新手:我的例子中的文本替换

    In my 红宝石 on Rails应用程序中 我的助手中有一个方法 它通过以下方式打开文件 content File open myfile txt The 文件内容就好像 my car my seat my age my son my
  • cron 爬虫使用 Ruby 中的 Google API 将数据插入 Google 电子表格的授权问题

    我的项目是每天早上 9 00 抓取某些网络数据并将它们放入我的 Google 电子表格中 并且它必须获得读取和写入某些内容的授权 这就是为什么下面的代码位于顶部 Google API CLIENT ID blah blah CLIENT S
  • 如何在 Rails 中制作动态下拉菜单?

    我正在开发一个电子商务项目 其中将有用于选择尺寸的单选按钮 我有一个数量下拉菜单 我想根据用户所选尺寸的可用库存使此下拉列表动态化 谁能告诉我如何在 Rails 上做到这一点 不会用大量的 javascript 扰乱我的视图文件 如果您使用
  • 在 Ruby 中处理 Zip 文件 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在ruby中仅在内存中创建zip文件 https stackoverflow com questions 11532502 how to create zip file only in memor
  • 基于模板参数条件创建成员别名 C++17

    因此 我试图简化通用类的使用 并遇到了以下想法 给出以下结构 template
  • 如何对 mongodb/mongoid 脚本进行基准测试,以比较两种不同的查询技术

    您对如何测试两种不同的 mongoid mongodb 查询实现的性能有什么建议吗 要比较的实现与以前的相关 问答 https stackoverflow com questions 10121977 extracting modellin
  • Ruby 单引号和双引号

    我最近一直在使用 Ruby 进行编码 并且之前使用过 Python 据我所知 单引号和双引号对代码的工作方式没有影响 我转向 Ruby 是为了了解它是如何工作的 并研究 Ruby 和 Python 之间的相似之处 我曾经使用过单引号字符串并
  • 向 Rails 应用程序中的内置类添加方法

    我想向 Rails 应用程序中的 Array 类添加一个方法 我应该把这个方法放在哪里 编辑得更清楚 显然我把它放在某个文件中 但是我如何告诉 Rails 应用程序在哪里可以找到它 执行此操作的一种方法是在以下位置创建一个文件lib rai
  • 使用旧的 ruby​​gems 版本进行捆绑安装

    我遇到的问题似乎与1个月前的问题 https stackoverflow com questions 38279896 rubygems 2 0 14 is not threadsafe bunder install message whe
  • Guard 不会加载 WDM

    我正在学习 Michael Hartl 的 Rails 教程 到目前为止该教程非常出色 我在高级设置一章中 他以有利于 TDD 的方式配置 Rails 环境 我安装了 Guard 并且通过运行我在 spec 文件夹中的测试 它一直正常运行
  • Ruby 依赖注入库

    我一直在研究一些 Ruby 依赖注入库 特别是 我检查了Needle http needle rubyforge org and Copland http copland rubyforge org 它们已经存在很长一段时间了 但用途并不多
  • 为什么这个 Ruby 方法返回“空值表达式”错误?

    我有这个简单的方法 def is palindrome sentence raise ArgumentError new expected string unless sentence is a String safe sentence s
  • 类、模块、它们的特征类和方法查找

    我们来开公开课吧Module并向其中添加一个方法 class Module def foo puts phew end end 我可以通过这样做来调用这个方法 Class foo 这是可以理解的 因为类Class is Class 其超类是
  • rvm编译安装ruby 2.5.0出错

    我正在尝试使用 rvm 安装 ruby 2 5 0 但出现错误 我在 Ubuntu 18 16 和现在的 Linux Mint Cinnamon 上尝试过 基本上我在运行安装 ruby 的代码之前所做的是 打开 GPG 密钥https rv
  • 如何阻止与 RSpec 和 Capybara 的外部连接?

    在我的 Rails 项目中 我想编写非理想条件的测试 例如缺乏互联网连接或超时 例如 我正在使用 gem 来联系 API 并且希望确保在我的应用程序和外部 API 之间存在连接问题时能够正确处理错误 我已经可以通过用录像机制作固定装置并从
  • Rails 4 - 如何链接到 PDF 文件(名称.PDF)?

    我正在生成 PDF 文件 我的链接如下所示 当我点击这个时 它会带我去 display invoice 123456789 这是一个 HTML 版本 在控制器中的操作如下 def display invoice if params invo
  • 红宝石边缘情况

    ruby 有一些边缘情况很难解释 因为解析会带来一些有趣的问题 我在这里列出其中两个 如果您知道更多 请添加到列表中 def foo 5 end this one works if tmp foo puts tmp to s end How
  • 转储 YAML 时如何强制使用双引号?

    我有一个小脚本来自动化 YAML 文件中的一些操作 我读取原始 YAML 文件并将其转换为哈希 然后dump http ruby doc org stdlib 1 8 6 libdoc yaml rdoc YAML html method
  • 预期的 ProductField,出现数组问题

    我有一个 Rails 4 应用程序 它有一个如下所示的 params 块 def store params params require store permit name description user id products attr
  • Watir 更改 Mozilla Firefox 首选项

    我正在使用 Watir 运行 Ruby 脚本来自动执行一些操作 我正在尝试自动将一些文件保存到某个目录 因此 在我的 Mozilla 设置中 我将默认下载目录设置为桌面并选择自动保存文件 然而 当我开始运行脚本时 这些更改并未反映出来 似乎

随机推荐

  • 请求 MTU 在 Nougat 中不起作用

    我正在开发与 BLE 设备通信的应用程序 我可以轻松地在特性上写入 20 个字节 但是当它超过 20 个字节时 就会产生问题 我正在使用 mBluetoothGatt requestMtu 512 写出成功后的特征 Override pub
  • 在 Swift 中实现 RCTEventEmitter 但未设置桥接收异常

    我正在尝试在 Swift 中实现 React Native 的事件发射器 以便我可以在我的一些本机模块中重用它 但是 当我从 iOS 本地发送事件时 收到以下错误 Bridge is not set This is probably bec
  • 强制下载 PNG,而不是使用 IIS 在浏览器中打开

    我需要能够下载所有 PNG 图像的子目录 而不是在浏览器窗口中打开 我使用 IIS 作为 Web 服务器 有没有办法强制 PNG 可下载 正如其他发帖者所说 您需要将 HTTP Content Disposition 标头 带有附件值 添加
  • 无法使用 yii\base\Object 作为对象,因为 'Object' 是一个特殊的类名 yii2 advance

    我刚刚买了一台更强大的电脑 安装了 Composer 并想在上面继续我的项目 但是当我使用 gii 时 它给了我这个错误 我该如何解决它 为什么我会得到它 谢谢 解决了 从2 0 13开始 类名Object自 PHP 7 2 起无效 请使用
  • 使用实体框架从存储过程中检索表数据

    我正在使用实体框架 v6 我有一个存储过程 如下所示 CREATE PROCEDURE dbo GetCountryList CustomerName VARCHAR MAX SearchCriteria VARCHAR MAX AS BE
  • 使用 Android NDK 和 C++

    我让示例 HelloJni 项目正常运行 它使用 C 文件作为本机代码 我无法获得任何使用 C 的简单示例 采取以下 JNI 代码 include
  • 有没有办法在 HTML/JavaScript 中指定多个图像源?

    有没有一种方法可以告诉浏览器查看图像 URL 列表 直到找到一个有效的 URL 纯 HTML 是首选 但我猜这里可能需要 JavaScript 我已经在使用 JQuery 所以这不是问题 编辑 感谢您的回答 我将添加一些说明 我所说的 作品
  • 仅当浏览器为 Firefox 时才使用 javascript 隐藏 html 元素

    如果浏览器仅限火狐浏览器 如何使用javascript隐藏div 检查 Firefox 浏览器 Javascript var FIREFOX Firefox i test navigator userAgent if FIREFOX doc
  • 编译失败,并显示“创建共享对象时不能使用针对‘.rodata.str1.8’的重定位 R_X86_64_32”

    我正在尝试从 VPS 中的 makefile 编译此源代码 但它不起作用 VPS 是 64 Cent 操作系统 这是完整的错误 make gcc c O3 w DLINUX I SDK amx SDK amx c g c O3 w DLIN
  • 将字典插入Python堆

    我正在尝试使用 键 值 构建一个堆 因此键是数字 值是字典 import heapq heap dic val 1 number 1 val 2 number 2 val 3 number 3 insetToHeap 2 dic heapq
  • 访问相邻组件/字段的最佳方式

    我正在寻找一种访问组件 字段的方法 这些组件 字段要么与访问的项目位于同一项目数组中 要么甚至仅位于同一父项目数组中 最后一个只是一个选项 在 ExtJS3 中 这很容易 只需定义一个ref在所有者容器中 但我没有在 ExtJS4 中找到类
  • R 根据行中的值在列中重复

    我有一个如下所示的数据框 Name School Weight Days Antoine Bach 0 03 5 Antoine Ken 0 02 7 Barbara Franklin 0 04 3 我想获得如下输出 Name School
  • Python sys.path - 附加 PYTHONPATH

    开始之前 我已经尝试完成它有一段时间了 但我没有运气 我正在尝试创建自己的 python 包 我将在项目中的单独文件中导入其中的模块 我尝试通过 sys 将项目的目录添加到 pythonpath 但 mod wsgi 仍然无法识别它 imp
  • 使用本地通知 ios 打开 url

    我已经搜索了一段时间试图找到答案 但似乎找不到 我想做的是让我的应用程序在后台运行时发送本地通知 并且当用户打开通知时 会将他们带到网站 我已全部设置完毕 但它一直打开应用程序而不是访问网站 我的问题是 这可能吗 如果是这样 您能看看我下面
  • 从源代码构建 Python3.7.3 缺少“_ctypes”

    我正在尝试从源代码构建Python 3 7 3ensurepip但我收到此错误 ModuleNotFoundError No module named ctypes 网上所有的答案都这么说libffi dev是需要的 但我已经安装了它 但它
  • Mobile Safari - 当最后一次触摸被删除时,“touchend”事件没有触发?

    我试图捕获的 手势 是当但仅当元素 其他或相同 已经触摸时的点击 因此 触摸 1 按下按钮 同时触摸 2 点击所选选项 触摸 1 释放并按下按钮 我遇到的问题是最后一点 当我释放最后一个手指时 touchend 事件没有被触发 那么我没有办
  • Android手机可以使用windows DirectX库吗?

    我有一些使用 Windows 中的 Direct X 库绘制游戏屏幕的函数 因此 我尝试使用 ndk 来使用 Android 手机中的功能 但我有一些问题 使用Java的Android手机可以识别Direct X功能吗 如果可以的话 我必须
  • git add --interactive“您编辑的块不适用”

    我正在尝试使用git add interactive有选择地向我的索引添加一些更改 但我不断收到 您编辑的大块不适用 再次编辑 消息 即使我选择 e 选项 我也会收到此消息 并立即保存 关闭我的编辑器 换句话说 如果根本不编辑该块 该补丁就
  • Rabbitmq Consumer_Timeout 行为未按预期工作?

    我很难证明consumer timeout设置正在按预期工作 我可能做错了或者误解了consumer timeout行为 我所有的测试代码都可以在这里找到 https github com Rafarel rabbitmq tests 基本
  • instance_eval 的块参数 - 已记录?目的?

    刚刚意识到instance eval yields self作为关联块的参数 1 9 2 版本中的错误除外 http www ruby forum com topic 189422 1 9 3p194 003 gt class C end