这是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的书中,有没有人有任何过时的例子,有没有什么文档列出了版本之间的所有特性变化?
1条答案
按热度按时间d8tt03nd1#
TL;DR
感谢@Stefan的bug跟踪链接,以及其他评论者的各种解释,您所指的功能有a ticket opened for deprecation and removal over 8 years ago。
详解及链接和引用
所以,Ruby目前没有做你所期望的事情,以及original Ruby book为什么不匹配所有Ruby实现的一些原因包括:
1.使用不同的编译器、语言、运行时和虚拟机的替代实现是一个移动的目标,并且许多当前的Ruby生态系统在原书中没有涉及。从那以后发生了很多变化。更多关于这个下面。
Ruby编程语言:你需要知道的一切,第一版。弗拉纳根,大卫和Yukihiro松本。O'Reilly Media; 2008年1月。
1.虽然从语言设计的Angular 来看,这本书中仍然有很多很好的参考资料,但从那时起,Ruby已经发生了很多变化,因此它不应该再被视为Ruby解释器或虚拟机如何实现各种内部的规范来源。
1.还有一些其他的书专注于Ruby内部,但据我所知,没有一本是真正针对Ruby >= 3.2.2的最新版本。
1.根据定义,Ruby语言如何实现的规范源代码是source code on GitHub,用于C和YARV的参考实现。其他Ruby实现,如TruffleRuby或JRuby,可能会以不同的方式实现,或者根本不实现。