NEWS for Ruby 3.0.0¶ ↑
本文件列出了自 **2.7.0** 版本以来的用户可见功能变更,不包括 bug 修复。
请注意,每个条目都保持简短,详细信息请参阅链接。
语言变更¶ ↑
-
关键字参数现在与位置参数分开。在 Ruby 2.7 中导致弃用警告的代码现在将导致
ArgumentError
或不同的行为。[Feature #14183] -
接受单个剩余参数和关键字的 Proc 现在不再受自动 splatting 的影响。这现在与接受单个剩余参数且没有关键字的 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
) 现已不再是实验性功能。[功能 #17260] -
单行模式匹配已重新设计。[实验性功能]
-
添加了查找模式。[实验性功能] [功能 #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
-
添加了无限方法定义。[实验性功能] [功能 #16746]
def square(x) = x * x
-
当使用
# frozen-string-literal: true
时,插值String
字面量不再被冻结。[功能 #17104] -
添加了魔法注释
shareable_constant_value
来冻结常量。有关更多详细信息,请参阅 魔法注释。[功能 #17273] -
引入了 静态分析 基础。
-
弃用警告默认情况下不再显示(从 Ruby 2.7.2 开始)。使用
-W:deprecated
(或使用-w
来显示其他警告)来打开它们。[功能 #16345] -
$SAFE
和$KCODE
现在是普通的全局变量,没有特殊行为。与$SAFE
相关的 C-API 方法已被删除。[功能 #16131] [功能 #17136] -
方法中单例类定义中的 yield 现在是
SyntaxError
,而不是警告。方法之外的类定义中的 yield 现在是SyntaxError
,而不是LocalJumpError
。[功能 #15575] -
当类变量被祖先类/模块中的相同定义覆盖时,现在会引发
RuntimeError
(以前,它只在详细模式下发出警告)。此外,从顶层作用域访问类变量现在是RuntimeError
。[错误 #14541] -
将值赋给编号参数现在会引发
SyntaxError
,而不是警告。
命令行选项¶ ↑
--help
选项¶ ↑
当环境变量 RUBY_PAGER
或 PAGER
存在且具有非空值,并且标准输入和输出为 tty 时,--help
选项将通过该值指定的分页器显示帮助信息。[功能 #16754]
--backtrace-limit
选项¶ ↑
--backtrace-limit
选项限制了回溯的最大长度。[功能 #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#wait 现在可以在非阻塞上下文中调用
block
/unblock
调度程序钩子。[功能 #16786]
-
-
-
添加了
ENV.except
,它返回一个不包含给定键及其值的哈希表。[功能 #15822]
-
-
-
添加了新的编码 IBM720。[功能 #16233]
-
在 Windows 上将
Encoding.default_external
的默认值更改为 UTF-8 [功能 #16604]
-
-
-
Fiber#blocking?
指示纤程是否为非阻塞。[功能 #16786] -
Fiber#backtrace
和Fiber#backtrace_locations
提供每个纤程的回溯。[功能 #16815] -
放宽了
Fiber#transfer
的限制。[Bug #17221]
-
-
GC.auto_compact=
和GC.auto_compact
已被添加用于控制何时运行压缩。将auto_compact=
设置为true
将导致压缩在主要收集期间发生。目前,压缩会给主要收集带来显著的开销,因此请先进行测试![功能 #17176]
-
-
-
Hash#transform_keys
和Hash#transform_keys!
现在接受一个哈希表,该哈希表将键映射到新键。[功能 #16274] -
添加了
Hash#except
,它返回一个排除给定键及其值的哈希表。[功能 #15822]
-
-
-
IO#nonblock?
现在默认为true
。[功能 #16786] -
IO#wait_readable
、IO#wait_writable
、IO#read
、IO#write
和其他相关方法(例如IO#puts
、IO#gets
)可能会在非阻塞执行上下文中调用调度程序钩子#io_wait(io, events, timeout)
。[功能 #16786]
-
-
-
当使用
freeze: false
关键字调用Kernel#clone
时,将使用freeze: false
关键字调用#initialize_clone
。[Bug #14266] -
Kernel#clone
当使用freeze: true
关键字调用时,将使用freeze: true
关键字调用#initialize_clone
,即使接收者未冻结,也会返回一个冻结的副本。[特性 #16175] -
Kernel#eval
当使用两个参数调用时,将在评估的代码中使用"(eval)"
作为__FILE__
和1
作为__LINE__
。[错误 #4352] -
Kernel#lambda
现在如果在没有字面块的情况下调用,会发出警告。[特性 #15973] -
Kernel.sleep
在非阻塞执行上下文中调用调度程序钩子#kernel_sleep(...)
。[特性 #16786]
-
-
-
Module#include
和Module#prepend
现在会影响已经包含或预先包含接收者的类和模块,反映了如果参数在其他模块和类包含或预先包含接收者之前包含在接收者中的行为。[特性 #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”方法现在接受包含方法名称列表的单个数组参数。[特性 #17314] -
Module#attr_accessor
,Module#attr_reader
,Module#attr_writer
和Module#attr
方法现在返回一个定义的方法名称数组作为符号。[特性 #17314] -
Module#alias_method
现在返回定义的别名作为符号。[特性 #17314]
-
-
互斥锁
-
Mutex
现在按每个Fiber
获取,而不是按每个Thread
获取。此更改应该与几乎所有用法兼容,并在使用调度程序时避免阻塞。[特性 #16792]
-
-
队列 / 有大小的队列
-
Queue#pop,SizedQueue#push 和相关方法现在可以在非阻塞上下文中调用
block
/unblock
调度程序钩子。[特性 #16786]
-
-
-
添加了新的类以启用并行执行。有关更多详细信息,请参见 ractor.md。
-
-
-
以下方法现在在子类实例上调用时返回或生成
String
实例,而不是子类实例:[Bug #10845]
-
-
-
Symbol#to_proc
现在返回一个 lambdaProc
。[功能 #16260] -
Symbol#name
已添加,如果符号已命名,则返回符号的名称。返回的字符串被冻结。[功能 #16150]
-
-
-
引入
Fiber.set_scheduler
用于拦截阻塞操作,以及Fiber.scheduler
用于访问当前调度程序。有关支持的操作以及如何实现调度程序钩子的更多详细信息,请参见 fiber.md。[功能 #16786] -
Fiber.blocking?
指示当前执行上下文是否处于阻塞状态。[功能 #16786] -
Thread#join
在非阻塞执行上下文中调用调度程序钩子block
/unblock
。[功能 #16786]
-
-
-
Thread.ignore_deadlock
访问器已添加,用于禁用默认的死锁检测,允许使用信号处理程序来打破死锁。[Bug #13768]
-
-
-
Warning#warn
现在支持类别关键字参数。[Feature #17122]
-
标准库更新¶ ↑
仅列出重要的更新。
-
-
更新到
BigDecimal
3.0.0 -
此版本与
Ractor
兼容。
-
-
-
更新到
Bundler
2.2.3
-
-
-
更新到 0.2.0
-
此版本与
Ractor
兼容。
-
-
-
更新到
CSV
3.1.9
-
-
-
更新到
Fiddle
1.0.5
-
-
-
更新到
IRB
1.2.6
-
-
-
将 :connect_timeout 添加到
TCPSocket.new
[Feature #17187]
-
-
-
Net::HTTP#verify_hostname=
和Net::HTTP#verify_hostname
已添加,用于跳过主机名验证。[Feature #16555] -
Net::HTTP.get
、Net::HTTP.get_response
和Net::HTTP.get_print
当第一个参数是URI
时,可以在第二个参数中将请求头作为Hash
传递。[Feature #16686]
-
-
Net::SMTP
-
添加 SNI 支持。
-
Net::SMTP.start 参数是关键字参数。
-
TLS 默认情况下不应检查主机名。
-
-
-
初始化不再是延迟的。[Bug #12136]
-
内置方法现在可以安全地覆盖。[Bug #15409]
-
实现仅使用以
!
结尾的方法。 -
与
Ractor
兼容。 -
使用已被官方弃用。请阅读
OpenStruct
中的注意事项 部分。
-
-
-
与
Ractor
兼容。
-
-
-
更新到
Reline
0.1.5
-
-
RubyGems
-
更新到 RubyGems 3.2.3
-
-
-
更新至
StringScanner
3.0.0 -
此版本与
Ractor
兼容。
-
-
-
URI.escape 和 URI.unescape 已被移除。请根据您的具体使用场景使用以下方法。
-
兼容性问题¶ ↑
不包括功能性错误修复。
-
Regexp
字面量和所有Range
对象都被冻结。[Feature #8948] [Feature #16377] [Feature #15504]/foo/.frozen? #=> true (42...).frozen? # => true
-
实验性:
Hash#each
一致地生成一个包含两个元素的数组。[Bug #12706]-
现在
{ a: 1 }.each(&->(k, v) { })
由于 lambda 的元数检查而引发ArgumentError
。
-
-
当写入重定向到已关闭管道的 STDOUT 时,现在不会显示任何管道破损错误消息。[Feature #14413]
-
TRUE
/FALSE
/NIL
常量不再被定义。 -
Integer#zero?
为了优化而覆盖了Numeric#zero?
。[Misc #16961] -
Enumerable#grep
和Enumerable#grep_v
当传递一个Regexp
且没有块时,不再修改Regexp.last_match
。[Bug #17030] -
要求 '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) 可以避免每次方法调用时的同步,因为它只使用原子操作。有关更多详细信息,请参阅工单。
-
-
在方法调用中使用关键字 splat 时分配的哈希数已减少到最多 1 个,并且将关键字 splat 传递给接受特定关键字的方法不会分配哈希。
-
super
在调用前一次调用中调用了相同类型的函数时,如果它不是细化或 attr reader 或 writer,则会进行优化。
JIT¶ ↑
-
JIT 代码的性能改进
-
微体系结构优化
-
在 JIT 压缩时,对多个方法共享的原生函数进行重复数据删除。
-
通过一些优化和冷路径分区来减少热路径的代码大小。
-
-
实例变量
-
消除一些冗余检查。
-
在方法中尽可能跳过多次检查类和对象。
-
优化一些核心类(如
Hash
及其子类)中的访问。
-
-
Method
内联支持一些 C 方法-
Kernel
:#class
,#frozen?
-
Integer
:#-@
,#~
,#abs
,#bit_length
,#even?
,#integer?
,#magnitude
,#odd?
,#ord
,#to_i
,#to_int
,#zero?
-
Struct
: 第 10 个或更高成员的 reader 方法
-
-
常量引用被内联。
-
始终根据接收方类生成适用于
==
、nil?
和!
调用的代码。 -
减少分支和方法返回时的 PC 访问次数。
-
稍微优化 C 方法调用。
-
-
编译过程改进
-
不再在 /tmp 中保留临时文件。
-
限制
GC
和 JIT 代码的压缩。 -
在不必要时避免对 JIT 代码进行 GC。
-
对 JIT 代码进行 GC 是在后台线程中执行的。
-
减少 Ruby 和 JIT 线程之间的锁数量。
-
静态分析¶ ↑
RBS¶ ↑
-
RBS 是一种用于 Ruby 程序类型定义的新语言。它允许使用高级类型(包括联合类型、重载、泛型和用于鸭子类型的接口类型)来编写类和模块的类型。
-
Ruby 附带核心/stdlib 类的类型定义。
-
rbs
gem 被捆绑在一起以加载和处理 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