NEWS for Ruby 4.0.0
本文档列出了自 3.4.0 版本以来用户可见的功能更改,不包括错误修复。
请注意,每个条目都保持得尽可能简洁,详情请参阅链接。
语言更改
-
*nil不再调用nil.to_a,类似于**nil不调用nil.to_hash。 [Feature #21047] -
行首的逻辑二进制运算符 (
||,&&,and和or) 会延续上一行,如同链式点操作符一样。以下代码示例是等效的if condition1 && condition2 ... end
先前
if condition1 && condition2 ... end
if condition1 && condition2 ... end
核心类更新
注意:此处仅列出重要的类更新。
-
-
Array#rfind已添加,作为array.reverse_each.find的更高效替代方案 [Feature #21678] -
Array#find已添加,作为Enumerable#find的更高效覆盖 [Feature #21678]
-
-
-
Binding#local_variables不再包含数字参数。此外,Binding#local_variable_get,Binding#local_variable_set, 和Binding#local_variable_defined?拒绝处理数字参数。 [Bug #21049] -
Binding#implicit_parameters,Binding#implicit_parameter_get, 和Binding#implicit_parameter_defined?已添加,用于访问数字参数和“it”参数。 [Bug #21049]
-
-
-
Enumerator.produce现在接受可选的size关键字参数来指定枚举的大小。它可以是整数、Float::INFINITY、可调用对象(如 lambda)或nil来表示未知大小。未指定时,大小默认为Float::INFINITY。# Infinite enumerator enum = Enumerator.produce(1, size: Float::INFINITY, &:succ) enum.size # => Float::INFINITY # Finite enumerator with known/computable size abs_dir = File.expand_path("./baz") # => "/foo/bar/baz" traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) { raise StopIteration if it == "/" File.dirname(it) } traverser.size # => 4
-
-
-
当引发
ArgumentError时,它现在会显示方法调用(调用者)和方法定义(被调用者)的代码片段。 [Feature #21543]
"' test.rb:1:in 'Object#add': wrong number of arguments (given 1, expected 2) (
ArgumentError)caller: test.rb:3 | add(1) ^^^ callee: test.rb:1 | def add(x, y) = x + y ^^^ from test.rb:3:in '<main>'“‘
-
-
-
引入对
Fiber#raise(cause:)参数的支持,类似于Kernel#raise。 [Feature #21360]
-
-
-
引入
Fiber::Scheduler#fiber_interrupt以使用给定异常中断 fiber。初始用例是在IO操作被关闭时中断正在等待阻塞IO操作的 fiber。 [Feature #21166] -
引入
Fiber::Scheduler#yield以允许在禁用信号异常时继续处理 fiber 调度器。 [Bug #21633] -
重新引入用于异步
IO#close的Fiber::Scheduler#io_close钩子。 -
刷新
IO写缓冲区时调用Fiber::Scheduler#io_write。 [Bug #21789]
-
-
-
File::Stat#birthtime现在在 Linux 上通过 statx 系统调用可用,前提是内核和文件系统支持。 [Feature #21205]
-
-
-
IO.select接受Float::INFINITY作为超时参数。 [Feature #20610] -
已移除通过以
|开头的IO类方法创建进程的已弃用行为。 [Feature #19630]
-
-
-
Kernel#inspect现在检查 instance_variables_to_inspect 方法是否存在,允许控制在 inspect 字符串中显示哪些实例变量class DatabaseConfig def initialize(host, user, password) @host = host @user = user @password = password end private def instance_variables_to_inspect = [:@host, :@user] end conf = DatabaseConfig.new("localhost", "root", "hunter2") conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
-
已移除通过以
|开头的Kernel#open创建进程的已弃用行为。 [Feature #19630]
-
-
-
添加了
Math.log1p和Math.expm1。 [Feature #21527]
-
-
-
Pathname已从默认 gem 提升为 Ruby 的核心类。 [Feature #17473]
-
-
-
Proc#parameters现在将匿名可选参数显示为[:opt]而不是[:opt, nil],使输出与匿名参数必需时保持一致。 [Bug #20974]
-
-
-
添加了
Ractor::Port类,用于 Ractor 之间通信的新同步机制。 [Feature #21262]port1 = Ractor::Port.new port2 = Ractor::Port.new Ractor.new port1, port2 do |port1, port2| port1 << 1 port2 << 11 port1 << 2 port2 << 12 end 2.times{ p port1.receive } #=> 1, 2 2.times{ p port2.receive } #=> 11, 12
Ractor::Port提供了以下方法因此,移除了
Ractor.yield和Ractor#take。 -
添加了
Ractor#join和Ractor#value以等待Ractor终止。这些类似于Thread#join和Thread#value。 -
添加了
Ractor#monitor和Ractor#unmonitor作为内部用于实现Ractor#join的低级接口。 -
Ractor.select现在只接受 Ractors 和 Ports。如果提供了 Ractors,它会在Ractor终止时返回。 -
添加了
Ractor#default_port。每个Ractor都有一个默认端口,由Ractor.send,Ractor.receive使用。 -
移除了
Ractor#close_incoming和Ractor#close_outgoing。 -
引入了
Ractor.shareable_proc和Ractor.shareable_lambda来创建可共享的Proc或 lambda。 [Feature #21550], [Feature #21557]
-
-
-
Range#to_set现在执行大小检查以防止出现无限范围的问题。 [Bug #21654] -
Range#overlap?现在正确处理无限(无界)范围。 [Bug #21185] -
已修复 beginless 整数范围的
Range#max行为。 [Bug #21174] [Bug #21175]
-
-
Ruby
-
定义了一个新的顶层模块
Ruby,其中包含 Ruby 相关的常量。此模块在 Ruby 3.4 中被保留,现在正式定义。 [Feature #20884]
-
-
-
一项新的(实验性)功能,用于提供定义之间的分离。有关“Ruby Box”的详细信息,请参阅 doc/language/box.md。 [Feature #21311] [Misc #21385]
-
-
Set
-
Set现在是核心类,而不是自动加载的标准库类。 [Feature #21216] -
Set#inspect现在使用更简单的显示,类似于字面量数组。(例如,Set[1, 2, 3]而不是#<Set: {1, 2, 3}>)。 [Feature #21389] -
传递参数给
Set#to_set和Enumerable#to_set已被弃用。 [Feature #21390]
-
-
-
Socket.tcp&TCPSocket.new接受open_timeout关键字参数来指定初始连接的超时时间。 [Feature #21347] -
当
TCPSocket.new中发生用户指定的超时时,之前可能根据情况引发Errno::ETIMEDOUT或IO::TimeoutError。此行为已统一,现在始终引发IO::TimeoutError。(请注意,在Socket.tcp中,在类似情况下仍可能引发Errno::ETIMEDOUT,并且在两种情况下,当超时发生在操作系统级别时,都可能引发Errno::ETIMEDOUT。)
-
-
-
Unicode 更新至 17.0.0 版本,Emoji 更新至 17.0 版本。 [Feature #19908][Feature #20724][Feature #21275] (也适用于
Regexp) -
String#strip,strip!,lstrip,lstrip!,rstrip, 和rstrip!已扩展以接受*selectors参数。 [Feature #21552]
-
-
-
引入对
Thread#raise(cause:)参数的支持,类似于Kernel#raise。 [Feature #21360]
-
标准库更新
我们仅列出值得注意的功能更改的标准库更改。
其他更改列在以下部分。如果以前捆绑的 Ruby 3.4.0 版本有 GitHub 发布,我们也列出了从该版本开始的发布历史。
以下捆绑的 gem 已从默认 gem 提升。
-
ostruct 0.6.3
-
pstore 0.2.0
-
0.1.4 到 v0.2.0
-
benchmark 0.5.0
-
logger 1.7.0
-
rdoc 7.0.3
-
6.14.0 到 v6.14.1, v6.14.2, v6.15.0, v6.15.1, v6.16.0, v6.16.1, v6.17.0, v7.0.0, v7.0.1, v7.0.2, v7.0.3
-
win32ole 1.9.2
-
1.9.1 到 v1.9.2
-
irb 1.16.0
-
reline 0.6.3
-
readline 0.0.4
-
fiddle 1.1.8
添加了以下默认 gem。
-
win32-registry 0.1.2
更新了以下默认 gem。
-
RubyGems 4.0.3
-
bundler 4.0.3
-
date 3.5.1
-
delegate 0.6.1
-
digest 3.2.1
-
3.2.0 到 v3.2.1
-
english 0.8.1
-
0.8.0 到 v0.8.1
-
erb 6.0.1
-
error_highlight 0.7.1
-
etc 1.4.6
-
fcntl 1.3.0
-
1.2.0 到 v1.3.0
-
fileutils 1.8.0
-
1.7.3 到 v1.8.0
-
forwardable 1.4.0
-
1.3.3 到 v1.4.0
-
io-console 0.8.2
-
0.8.1 到 v0.8.2
-
io-nonblock 0.3.2
-
io-wait 0.4.0
-
0.3.2 到 v0.3.3, v0.3.5.test1, v0.3.5, v0.3.6, v0.4.0
-
ipaddr 1.2.8
-
json 2.18.0
-
2.9.1 到 v2.10.0, v2.10.1, v2.10.2, v2.11.0, v2.11.1, v2.11.2, v2.11.3, v2.12.0, v2.12.1, v2.12.2, v2.13.0, v2.13.1, v2.13.2, v2.14.0, v2.14.1, v2.15.0, v2.15.1, v2.15.2, v2.16.0, v2.17.0, v2.17.1, v2.18.0
-
net-http 0.9.1
-
openssl 4.0.0
-
optparse 0.8.1
-
pp 0.6.3
-
0.6.2 到 v0.6.3
-
prism 1.7.0
-
psych 5.3.1
-
resolv 0.7.0
-
stringio 3.2.0
-
3.1.2 到 v3.1.3, v3.1.4, v3.1.5, v3.1.6, v3.1.7, v3.1.8, v3.1.9, v3.2.0
-
strscan 3.1.6
-
time 0.4.2
-
0.4.1 到 v0.4.2
-
timeout 0.6.0
-
uri 1.1.1
-
weakref 0.1.4
-
0.1.3 到 v0.1.4
-
zlib 3.2.2
-
3.2.1 到 v3.2.2
以下捆绑 gem 已更新。
-
minitest 6.0.0
-
power_assert 3.0.1
-
rake 13.3.1
-
test-unit 3.7.5
-
3.6.7 到 3.6.8, 3.6.9, 3.7.0, 3.7.1, 3.7.2, 3.7.3, 3.7.4, 3.7.5
-
rexml 3.4.4
-
rss 0.3.2
-
0.3.1 到 0.3.2
-
net-ftp 0.3.9
-
0.3.8 到 v0.3.9
-
net-imap 0.6.2
-
0.5.8 到 v0.5.9, v0.5.10, v0.5.11, v0.5.12, v0.5.13, v0.6.0, v0.6.1, v0.6.2
-
net-smtp 0.5.1
-
0.5.0 到 v0.5.1
-
matrix 0.4.3
-
0.4.2 到 v0.4.3
-
prime 0.1.4
-
0.1.3 到 v0.1.4
-
rbs 3.10.0
-
3.8.0 到 v3.8.1, v3.9.0.dev.1, v3.9.0.pre.1, v3.9.0.pre.2, v3.9.0, v3.9.1, v3.9.2, v3.9.3, v3.9.4, v3.9.5, v3.10.0.pre.1, v3.10.0.pre.2, v3.10.0
-
typeprof 0.31.1
-
debug 1.11.1
-
1.11.0 到 v1.11.1
-
base64 0.3.0
-
0.2.0 到 v0.3.0
-
bigdecimal 4.0.1
-
3.1.8 到 v3.2.0, v3.2.1, v3.2.2, v3.2.3, v3.3.0, v3.3.1, v4.0.0, v4.0.1
-
drb 2.2.3
-
2.2.1 到 v2.2.3
-
syslog 0.3.0
-
0.2.0 到 v0.3.0
-
csv 3.3.5
-
repl_type_completor 0.1.12
RubyGems 和 Bundler
Ruby 4.0 捆绑的 RubyGems 和 Bundler 版本为 4。有关详细信息,请参阅以下链接。
支持的平台
-
Windows
-
放弃支持早于 14.0 (_MSC_VER 1900) 的 MSVC 版本。这意味着现在需要 Visual Studio 2015 或更高版本。
-
兼容性问题
-
以下方法已从
Ractor中移除,因为添加了Ractor::Port-
Ractor.yield -
Ractor#take -
Ractor#close_incoming -
Ractor#close_outgoing
-
-
ObjectSpace._id2ref已弃用。 [Feature #15408] -
已移除
Process::Status#&和Process::Status#>>。它们在 Ruby 3.3 中已被弃用。 [Bug #19868] -
已移除
rb_path_check。此函数用于 $SAFE 路径检查,该检查在 Ruby 2.7 中已被移除,并且已经弃用。 [Feature #20971] -
“参数数量错误”的
ArgumentError的回溯现在包含接收者的类或模块名(例如,在Foo#bar中而不是在bar中)。 [Bug #21698] -
回溯不再显示
internal帧。这些方法现在显示得好像它们在 Ruby 源代码文件中一样,与其他 C 实现的方法一致。 [Bug #20968]
之前: ruby -e '[1].fetch_values(42)' <internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError) from <internal:array>:211:in 'block in Array#fetch_values' from <internal:array>:211:in 'Array#map!' from <internal:array>:211:in 'Array#fetch_values' from -e:1:in '<main>'
之后: $ ruby -e '[1].fetch_values(42)' -e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError) from -e:1:in '<main>'
标准库兼容性问题
-
CGI库已从默认 gem 中移除。现在我们只为以下方法提供cgi/escape -
随着
Set从标准库迁移到核心类,set/sorted_set.rb已被移除,SortedSet不再是自动加载的常量。请安装sorted_setgem 并require 'sorted_set'来使用SortedSet。 [Feature #21287] -
-
已移除当请求带有正文(例如
POST、PUT)且未显式设置Content-Type头时,自动将Content-Type头设置为application/x-www-form-urlencoded的默认行为。如果您的应用程序依赖于此自动默认设置,您的请求现在将不带 Content-Type 头发送,这可能会破坏与某些服务器的兼容性。 [GH-net-http #205]
-
C API 更新
-
-
rb_thread_fd_close已弃用,现在是空操作。如果您需要将 C 扩展中的文件描述符暴露给 Ruby 代码,请使用RUBY_IO_MODE_EXTERNAL创建一个IO实例,并使用rb_io_close(io)来关闭它(这也会中断并等待IO实例上的所有待处理操作)。直接关闭文件描述符不会中断待处理操作,并可能导致未定义行为。换句话说,如果两个IO对象共享同一个文件描述符,关闭一个不会影响另一个。 [Feature #18455]
-
-
GVL
-
rb_thread_call_with_gvl现在可以有 GVL 或无 GVL 地工作。这允许 gem 避免检查ruby_thread_has_gvl_p。请继续注意 GVL。 [Feature #20750]
-
-
Set
-
已添加
Set的 C API。支持以下方法:[Feature #21459]-
rb_set_foreach -
rb_set_new -
rb_set_new_capa -
rb_set_lookup -
rb_set_add -
rb_set_clear -
rb_set_delete -
rb_set_size
-
-
实现改进
-
Class#new(例如Object.new)在所有情况下都更快,尤其是在传递关键字参数时。这也已集成到 YJIT 和 ZJIT 中。 [Feature #21254] -
不同大小池的
GC堆现在独立增长,当只有某些池包含长期存在的对象时,可减少内存使用量 -
大型对象的页面上的
GC清扫速度更快 -
“通用 ivar”对象(
String、Array、TypedData等)现在使用新的内部“fields”对象来加快实例变量访问速度 -
GC避免维护内部id2ref表,直到首次使用它,从而加快object_id分配和GC清扫速度 -
类和模块对象的
object_id和hash速度更快 -
较大的 bignum 整数可以通过可变宽度分配保持嵌入
-
Random,Enumerator::Product,Enumerator::Chain,Addrinfo,StringScanner,以及一些内部对象现在受到写屏障保护,这减少了GC的开销。
Ractor
在提高 Ractor 的稳定性、性能和可用性方面付出了大量努力。这些改进使 Ractor 的实现更接近于离开实验状态。
-
性能改进
-
冻结字符串和符号表在内部使用无锁哈希集合 [Feature #21268]
-
方法缓存查找在大多数情况下避免了锁定
-
类(和通用 ivar)实例变量访问更快,并避免了锁定
-
通过使用每个 Ractor 的计数器,避免了对象分配中的 CPU 缓存争用
-
通过使用线程本地计数器,避免了 xmalloc/xfree 中的 CPU 缓存争用
-
object_id在大多数情况下避免了锁定
-
-
错误修复和稳定性
-
修复了在 Ractor 和 Thread 结合时可能发生的死锁
-
修复了 Ractor 中
require和autoload的问题 -
修复了跨 Ractor 的编码/转码问题
-
修复了
GC操作和方法无效化中的竞态条件 -
修复了启动 Ractor 后进程 fork 的问题
-
Ractor 下的
GC分配计数现在是准确的 -
修复了
GC后 TracePoints 不工作的问题 [Bug #19112]
-
JIT
-
ZJIT
-
引入了一个实验性的基于方法的 JIT 编译器。在可用情况下,可以通过
--zjit选项或调用RubyVM::ZJIT.enable在运行时启用 ZJIT。构建 Ruby 时,需要 Rust 1.85.0 或更高版本才能包含 ZJIT 支持。 -
截至 Ruby 4.0.0,ZJIT 比解释器快,但尚未达到 YJIT 的速度。我们鼓励尝试 ZJIT,但建议暂时不要在生产环境中使用它。
-
我们的目标是在 Ruby 4.1 中使 ZJIT 比 YJIT 更快且生产环境就绪。
-
-
YJIT
-
-
ratio_in_yjit在默认构建中不再工作。请在configure上使用--enable-yjit=stats在--yjit-stats上启用它。 -
向默认统计信息添加了
invalidate_everything,当所有代码被TracePoint失效时,此计数器会递增。
-
-
向
RubyVM::YJIT.enable添加了mem_size:和call_threshold:选项。
-
-
RJIT
-
已移除
--rjit。我们将把第三方 JIT API 的实现移至 ruby/rjit 仓库。
-