Ruby Proc.new在隐式块的方法中不再受支持?

2lpgd968  于 2023-08-04  发布在  Ruby
关注(0)|答案(1)|浏览(103)

这是Matz书中的一小段摘录:
如果Proc.new是在没有块的情况下从一个方法中调用的,而该方法有阿索块,那么它返回一个proc,表示与包含方法相关联的块。以这种方式使用Proc.new提供了在方法定义中使用带&号前缀的块参数的替代方案。以下两种方法是等效的,例如:

def invoke(&b) 
  b.call
end

def invoke 
    Proc.new.call
end

字符串
这是我的理解。但是,在升级到Ruby V之后,3.1.2,似乎不再是方法等同的情况。现在,如果我调用这两个方法,那么:

def invoke(&b) 
  b.call
end

def invoke2 
  Proc.new.call
end

invoke {puts 'hello'}
invoke2 {puts 'hello'}

hello
test.rb:6:in `new': tried to create Proc object without a block (ArgumentError)


我四处寻找原因,并在这里发现了一些有趣的信息:
Can a Ruby method access the implicit block argument?在这篇文章中,Stefan的回答引用了v中的文档。2.7.1因此:
::new可以在没有块的情况下被调用,只有在附加了块的方法中,在这种情况下,该块被转换为Proc对象。
然而,这一点散文已经神秘地从3.1.2文档中消失了。
Jörg W Mittag有一个有趣的答案:
[这]实际上是在MRI中实现Proc::new的一个意外的副作用:Proc::new没有检查你是否传递了一个块,它只是假设你传递了一个块,并将第一个块从内部VM堆栈顶部移除。所以,如果你没有将一个块传递给Proc::new,它实际上会为传递给方法的隐式块创建一个Proc(因为它恰好位于堆栈顶部)。
但是,这从来不是可移植的,从来没有保证,从来没有在所有Ruby实现中工作,AFAIK也不再在YARV中工作。
这些信息表明,该功能可能随时消失。
在文档存档中,我发现能够做到这一点的最后一个版本是3.0.5。下一个版本,3.1.0,没有大张旗鼓地删除了引用的段落。
我所寻找的是某种明确的声明,说明在没有显式块参数的方法中,Proc.new的使用在such等等版本中不再被支持。有人有这样的吗?
我更广泛的担忧是,我曾认为马茨的书是真理的源泉,现在我发现它有一小部分已经过时了。在Matz的书中,有没有人有任何过时的例子,有没有什么文档列出了版本之间的所有特性变化?

d8tt03nd

d8tt03nd1#

TL;DR

感谢@Stefan的bug跟踪链接,以及其他评论者的各种解释,您所指的功能有a ticket opened for deprecation and removal over 8 years ago

详解及链接和引用

所以,Ruby目前没有做你所期望的事情,以及original Ruby book为什么不匹配所有Ruby实现的一些原因包括:
1.使用不同的编译器、语言、运行时和虚拟机的替代实现是一个移动的目标,并且许多当前的Ruby生态系统在原书中没有涉及。从那以后发生了很多变化。更多关于这个下面。

  1. Ruby 3.0.0中删除了(mis-)特性,但直到Ruby v3_0_0_rc2-166-g8 da 7 f4 abc 7中将this commit合并到 proc.c 中时,文档才更新。
  2. The book you're referring to至少在15年前编写并出版。这本书的引文,这是仍然可以在亚马逊和从O 'Reilly是:
    Ruby编程语言:你需要知道的一切,第一版。弗拉纳根,大卫和Yukihiro松本。O'Reilly Media; 2008年1月。
    1.虽然从语言设计的Angular 来看,这本书中仍然有很多很好的参考资料,但从那时起,Ruby已经发生了很多变化,因此它不应该再被视为Ruby解释器或虚拟机如何实现各种内部的规范来源。
    1.还有一些其他的书专注于Ruby内部,但据我所知,没有一本是真正针对Ruby >= 3.2.2的最新版本。
  3. Pragmatic Programmers即将出版的名为Programming Ruby 3.2, 5th Ed. by Noel Rappin et al.的书可能会更新,但这本书的beta版的“大纲”表明,它并没有在内部溢出很多墨水,但可能会涵盖显着的变化。
  • 注:这个特定的用例是否足够值得注意,对于目前标题为“Ruby更改”的附录来说,我无法猜测,但由于这本书处于测试阶段,如果你觉得它很重要,你可以随时参与测试并建议它的包含。

1.根据定义,Ruby语言如何实现的规范源代码是source code on GitHub,用于C和YARV的参考实现。其他Ruby实现,如TruffleRubyJRuby,可能会以不同的方式实现,或者根本不实现。

  1. reference implementation maintains an issue tracker可以用于发现关于过去,未决或拒绝的功能更改的讨论,但当涉及到代码如何实现时,它不一定是与实际源代码相同的规范,尽管它肯定应该指向影响它们的提交。
  • 早在2.0.0版本的参考实现的官方文档就可以在https://docs.ruby-lang.org/en/上找到,但许多人也依赖于https://ruby-doc.org/。目前,后者包括关于点释放的信息,而前者不包括。YMMV
  • Proc core class for Ruby 3.2来自ruby-lang.org
  • Proc core class for Ruby 3.2.2来自ruby-doc.org
  • 继续使用旧的书作为关于Ruby是如何设计的参考,但请迁移到较新的书和规范源,以解决有关特定实现问题的问题。如果您正在讨论不常见的用法、边缘情况、替代实现或特定于平台的问题,这一点尤其重要。

相关问题