NEWS for Ruby 3.0.0
本文档列出了自 2.7.0 版本以来的用户可见功能更改,不包括错误修复。
请注意,每个条目都保持得尽可能简洁,详情请参阅链接。
语言更改
-
关键字参数现在与位置参数分离。在 Ruby 2.7 中会导致警告的代码现在会导致
ArgumentError或不同的行为。[Feature #14183] -
接受单个 rest 参数和关键字的 Proc 不再进行自动扩展。这现在与接受单个 rest 参数但没有关键字的 Proc 的行为匹配。[Feature #16166]
pr = proc{|*a, **kw| [a, kw]} pr.call([1]) # 2.7 => [[1], {}] # 3.0 => [[[1]], {}] pr.call([1, {a: 1}]) # 2.7 => [[1], {:a=>1}] # and deprecation warning # 3.0 => [[[1, {:a=>1}]], {}]
-
参数转发 (
...) 现在支持前导参数。[Feature #16378]def method_missing(meth, ...) send(:"do_#{meth}", ...) end
-
模式匹配 (
case/in) 不再是实验性的。[Feature #17260] -
单行模式匹配已重新设计。[实验性]
-
添加了
=>。它可以用作右向赋值。[Feature #17260]0 => a p a #=> 0 {b: 0, c: 1} => {b:} p b #=> 0
-
in的返回值已更改为true或false。[Feature #17371]# version 3.0 0 in 1 #=> false # version 2.7 0 in 1 #=> raise NoMatchingPatternError
-
-
添加了查找模式。[实验性] [Feature #16828]
case ["a", 1, "b", "c", 2, "d", "e", "f", 3] in [*pre, String => x, String => y, *post] p pre #=> ["a", 1] p x #=> "b" p y #=> "c" p post #=> [2, "d", "e", "f", 3] end
-
添加了无尽方法定义。[实验性] [Feature #16746]
def square(x) = x * x
-
使用
# frozen-string-literal: true时,插值String字面量不再是冻结的。[Feature #17104] -
添加了魔法注释
shareable_constant_value来冻结常量。更多详情请参阅 魔法注释。[Feature #17273] -
引入了 静态分析 的基础。
-
默认不再显示弃用警告(自 Ruby 2.7.2 起)。使用
-W:deprecated打开它们(或使用-w显示其他警告)。[Feature #16345] -
$SAFE和$KCODE现在是正常的全局变量,没有特殊行为。与$SAFE相关的 C-API 方法已被移除。[Feature #16131] [Feature #17136] -
在方法中的单例类定义中使用 yield 现在是
SyntaxError而不是警告。在方法外的类定义中使用 yield 现在是SyntaxError而不是LocalJumpError。[Feature #15575] -
当类变量被祖先类/模块中的同一定义覆盖时,现在会引发
RuntimeError(以前,在详细模式下只发出警告)。此外,从顶层作用域访问类变量现在是RuntimeError。[Bug #14541] -
为数字参数赋值现在是
SyntaxError而不是警告。
命令行选项
--help 选项
当环境变量 RUBY_PAGER 或 PAGER 存在且有非空值,并且标准输入输出为 tty 时,--help 选项会通过指定值的分页器显示帮助信息。[Feature #16754]
--backtrace-limit 选项
--backtrace-limit 选项限制了回溯的最大长度。[Feature #8661]
核心类更新
仅列出未解决的问题。
-
-
可以使用
Enumerator::ArithmeticSequence进行切片dirty_data = ['--', 'data1', '--', 'data2', '--', 'data3'] dirty_data[(1..).step(2)] # take each second element # => ["data1", "data2", "data3"]
-
-
Binding#eval当只带一个参数调用时,在计算的代码中将使用"(eval)"作为__FILE__,使用1作为__LINE__。[Bug #4352] [Bug #17419]
-
-
ConditionVariable
-
ConditionVariable#wait 现在可能在非阻塞上下文中调用
block/unblock调度器钩子。[Feature #16786]
-
-
-
Dir.glob和Dir.[]现在默认对结果进行排序,并接受sort:关键字选项。[Feature #8709]
-
-
-
已添加
ENV.except,它返回一个排除给定键及其值的哈希。[Feature #15822] -
Windows:将 ENV 名称和值读取为 UTF-8 编码的字符串 [Feature #12650]
-
-
-
添加了新的编码 IBM720。[Feature #16233]
-
更改了 Windows 上
Encoding.default_external的默认值,使其为 UTF-8 [Feature #16604]
-
-
-
Fiber.new(blocking: true/false) 允许您创建非阻塞执行上下文。[Feature #16786] -
Fiber#blocking?告诉您协程是否是非阻塞的。[Feature #16786] -
Fiber#backtrace和Fiber#backtrace_locations提供每个协程的回溯。[Feature #16815] -
放宽了
Fiber#transfer的限制。[Bug #17221]
-
-
-
添加了 GC.auto_compact= 和 GC.auto_compact 来控制何时运行压缩。将
auto_compact=设置为true将导致在主要收集期间进行压缩。目前,压缩会给主要收集带来显著的开销,请先进行测试![Feature #17176]
-
-
-
Hash#transform_keys和Hash#transform_keys!现在接受一个映射键到新键的哈希。[Feature #16274] -
已添加
Hash#except,它返回一个排除给定键及其值的哈希。[Feature #15822]
-
-
-
IO#nonblock?现在默认为true。[Feature #16786] -
IO#wait_readable、IO#wait_writable、IO#read、IO#write以及其他相关方法(例如IO#puts、IO#gets)可能在非阻塞执行上下文中调用调度器钩子 io_wait(io, events, timeout)。[Feature #16786]
-
-
-
当使用
freeze: false关键字调用Kernel#clone时,将使用freeze: false关键字调用 initialize_clone。[Bug #14266] -
当使用
freeze: true关键字调用Kernel#clone时,将使用freeze: true关键字调用 initialize_clone,即使接收者未冻结,也将返回一个冻结的副本。[Feature #16175] -
Kernel#eval当带有两个参数调用时,在计算的代码中将使用"(eval)"作为__FILE__,使用1作为__LINE__。[Bug #4352] -
Kernel#lambda现在会在没有字面量块时发出警告。[Feature #15973] -
Kernel.sleep在非阻塞执行上下文中调用调度器钩子 kernel_sleep(…)。[Feature #16786]
-
-
Module
-
Module#include和Module#prepend现在会影响已包含或预置了接收者的类和模块,这与在其他模块和类包含或预置接收者之前将参数包含在接收者中的行为一致。[Feature #9573]class C; end module M1; end module M2; end C.include M1 M1.include M2 p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject]
-
Module#public、Module#protected、Module#private、Module#public_class_method、Module#private_class_method,以及顶层“private”和“public”方法现在接受包含方法名称列表的单个数组参数。[Feature #17314] -
Module#attr_accessor、Module#attr_reader、Module#attr_writer和Module#attr方法现在返回已定义方法名称的符号数组。[Feature #17314] -
Module#alias_method现在返回定义的别名作为符号。[Feature #17314]
-
-
Mutex
-
Mutex现在是按Fiber而不是按Thread获取的。此更改对于几乎所有用法都应该是兼容的,并避免了在使用调度器时的阻塞。[Feature #16792]
-
-
-
Proc#==和Proc#eql?现在已定义,并且对于从同一块创建的独立Proc实例将返回 true。[Feature #14267]
-
-
Queue / SizedQueue
-
Queue#pop、SizedQueue#push 及相关方法现在可能在非阻塞上下文中调用
block/unblock调度器钩子。[Feature #16786]
-
-
-
添加了新类以实现并行执行。更多详情请参阅 ractor.md。
-
-
-
Random::DEFAULT现在指向Random类而不是Random实例,因此它可以与Ractor一起使用。[Feature #17322] -
Random::DEFAULT已弃用,因为其值现在令人困惑且不再是全局的,请直接使用Kernel.rand/Random.rand,或使用Random.new创建Random实例。[Feature #17351]
-
-
-
当在子类实例上调用时,以下方法现在返回或产生
String实例而不是子类实例:[Bug #10845]
-
-
-
Symbol#to_proc现在返回一个 lambdaProc。[Feature #16260] -
已添加
Symbol#name,它返回符号的名称(如果它有名称)。返回的字符串是冻结的。[Feature #16150]
-
-
-
引入
Fiber.set_scheduler用于拦截阻塞操作,以及Fiber.scheduler用于访问当前调度器。有关支持的操作以及如何实现调度器钩子的更多信息,请参阅 fiber.md。[Feature #16786] -
Fiber.blocking?告诉当前执行上下文是否正在阻塞。[Feature #16786]
-
-
-
Thread#join在非阻塞执行上下文中调用调度器钩子block/unblock。[Feature #16786] -
添加了
Thread.ignore_deadlock访问器,用于禁用默认的死锁检测,允许使用信号处理器来打破死锁。[Bug #13767]
-
-
-
Warning#warn现在支持类别关键字参数。[Feature #17122]
-
标准库更新
仅列出未解决的问题。
-
-
更新到
BigDecimal3.0.0 -
此版本与
Ractor兼容。
-
-
-
更新到
Bundler2.2.3
-
-
-
更新到 0.2.0
-
此版本与
Ractor兼容。
-
-
CSV
-
更新到 CSV 3.1.9
-
-
Fiddle
-
更新到 Fiddle 1.0.5
-
-
IRB
-
更新到 IRB 1.2.6
-
-
Set
-
-
在
TCPSocket.new中添加 :connect_timeout [Feature #17187]
-
-
-
添加了
Net::HTTP#verify_hostname=和Net::HTTP#verify_hostname以跳过主机名验证。[Feature #16555] -
当第一个参数是
URI时,Net::HTTP.get、Net::HTTP.get_response和Net::HTTP.get_print可以在第二个参数中接受一个Hash作为请求头。[Feature #16686]
-
-
Net::SMTP
-
添加 SNI 支持。
-
Net::SMTP.start 参数是关键字参数。
-
默认情况下,TLS 不应检查主机名。
-
-
-
初始化不再是惰性的。[Bug #12136]
-
内置方法现在可以安全地覆盖。[Bug #15409]
-
实现仅使用以
!结尾的方法。 -
与
Ractor兼容。 -
使用官方不推荐。请阅读
OpenStruct部分的 注意事项。
-
-
-
与
Ractor兼容。
-
-
Reline
-
更新到 Reline 0.1.5
-
-
RubyGems
-
更新到 RubyGems 3.2.3
-
-
-
更新到
StringScanner3.0.0 -
此版本与
Ractor兼容。
-
-
-
已移除 URI.escape 和 URI.unescape。根据您的具体用例,请改用以下方法。
-
兼容性问题
不包括功能性错误修复。
-
Regexp字面量和所有Range对象都被冻结。[Feature #8948] [Feature #16377] [Feature #15504]/foo/.frozen? #=> true (42...).frozen? # => true
-
实验性:
Hash#each一致地产生一个 2 元素数组。[Bug #12706]-
现在
{ a: 1 }.each(&->(k, v) { })会因 lambda 的元数检查而引发ArgumentError。
-
-
当向重定向到已关闭管道的 STDOUT 写入时,现在不会显示 Broken pipe 错误消息。[Feature #14413]
-
TRUE/FALSE/NIL常量不再被定义。 -
Integer#zero?为了优化而覆盖了Numeric#zero?。[Misc #16961] -
当传入
Regexp且没有块时,Enumerable#grep和Enumerable#grep_v不再修改Regexp.last_match。[Bug #17030] -
require 'open-uri' 不再重新定义
Kernel#open。请直接调用URI.open或使用use URI#open。[Misc #15893] -
出于依赖和性能原因,SortedSet 已被移除。
标准库兼容性问题
-
默认 gem
-
以下库已从标准库提升为默认 gem。
-
abbrev
-
base64
-
drb
-
debug
-
erb
-
find
-
net-ftp
-
net-http
-
net-imap
-
net-protocol
-
open-uri
-
optparse
-
pp
-
prettyprint
-
resolv-replace
-
resolv
-
rinda
-
set
-
securerandom
-
shellwords
-
tempfile
-
tmpdir
-
time
-
tsort
-
un
-
weakref
-
以下扩展已从标准库提升为默认 gem。
-
digest
-
io-nonblock
-
io-wait
-
nkf
-
pathname
-
syslog
-
win32ole
-
-
-
捆绑 gem
-
net-telnet 和 xmlrpc 已从捆绑 gem 中移除。如果您有兴趣维护它们,请在 github.com/ruby/xmlrpc 或 github.com/ruby/net-telnet 上评论您的计划。
-
-
SDBM 已从 Ruby 标准库中移除。[Bug #8446]
-
sdbm 的问题将在 github.com/ruby/sdbm 处理
-
-
WEBrick 已从 Ruby 标准库中移除。[Feature #17303]
-
WEBrick 的问题将在 github.com/ruby/webrick 处理
-
C API 更新
-
与
$SAFE相关的 C API 函数已被移除。[Feature #16131] -
C API 头文件
ruby/ruby.h已拆分。[GH-2991]这应该对扩展库没有影响,但用户可能会遇到编译速度变慢的情况。
-
内存视图接口 [实验性]
-
内存视图接口是一组 C API,用于在扩展库之间交换原始内存区域,例如数值数组或位图图像。扩展库还可以共享内存区域的元数据,这些元数据由形状、元素格式等组成。利用这些元数据,扩展库甚至可以适当地共享多维数组。此功能参考了 Python 的缓冲区协议进行设计。[Feature #13767] [Feature #14722]
-
-
引入了与
Ractor相关的 C API(实验性),位于 “include/ruby/ractor.h”。
实现改进
-
为
Ractor引入了新的方法缓存机制。[Feature #16614]-
由 ISeq 指向的内联方法缓存可以被多个 Ractor 并行访问,并且即使是方法缓存也需要同步。然而,这种同步可能会产生开销,因此引入了新的内联方法缓存机制:(1) 可丢弃内联方法缓存 (2) 每个类的缓存 (3) 新的失效机制。(1) 仅使用原子操作就可以避免每次方法调用的同步。详情请参阅工单。
-
-
使用关键字展开符调用方法时分配的哈希数量已减少到最多 1 个,将关键字展开符传递给接受特定关键字的方法不会分配哈希。
-
当上一次调用是相同类型的自分引用的方法(不是 refinements、attr reader 或 writer)时,
super得到了优化。
JIT
-
JIT 编译代码的性能改进
-
微架构优化
-
多个方法共享的原生函数在 JIT 压缩时去重。
-
通过一些优化和分区冷路径来减小热路径的代码大小。
-
-
实例变量
-
消除了一些冗余检查。
-
在可能的情况下,跳过方法中对类和对象的多次检查。
-
优化了一些核心类(如
Hash)及其子类的访问。
-
-
支持一些 C 方法的内联
-
常量引用被内联。
-
始终为
==、nil?和!调用生成适当的代码,具体取决于接收者类。 -
减少分支和方法返回时的 PC 访问次数。
-
对 C 方法调用进行了一些优化。
-
-
编译过程改进
-
不再在 /tmp 中保留临时文件。
-
限制 JIT 代码的
GC和压缩。 -
在不必要时避免 GC 收集 JIT 代码。
-
JIT 代码的 GC 收集在后台线程中执行。
-
减少 Ruby 和 JIT 线程之间的锁数量。
-
静态分析
RBS
-
RBS 是一种用于 Ruby 程序类型定义的新语言。它允许使用高级类型(包括联合类型、重载、泛型和用于鸭子类型的接口类型)来编写类和模块的类型。
-
Ruby 提供了核心/标准库类的类型定义。
-
捆绑了
rbsgem 以加载和处理 RBS 文件。
TypeProf
-
TypeProf 是一个基于抽象解释的 Ruby 代码类型分析工具。
-
它读取未加注解的 Ruby 代码,尝试推断其类型签名,并以 RBS 格式打印分析结果。
-
尽管它目前仅支持 Ruby 语言的一个子集,但我们将持续改进语言特性覆盖范围、分析性能和可用性。
-
# test.rb def foo(x) if x > 10 x.to_s else nil end end foo(42)
$ typeprof test.rb # Classes class Object def foo : (Integer) -> String? end
杂项更改
-
使用
ruby2_keywords的方法将不再保留空的关键字展开符,这些现在与不使用ruby2_keywords的方法一样被移除。 -
当异常在默认处理程序中被捕获时,错误消息和回溯将按从内到外的顺序打印。[Feature #8661]
-
访问未初始化的实例变量不再在详细模式下发出警告。[Feature #17055]