Ruby 3.0有什么新内容?

351 阅读3分钟

Ruby和类型

RBS是描述Ruby程序中类型的新语言。 像SorbetSteep或新引入的TypeProf这样的类型检查器可以使用这些类型对程序进行静态分析。 下面是一个取自RBS文档的简单例子。

# Actual code
class User
  attr_reader :login, :email

  def initialize(login:, email:)
    @login, @email = login, email
  end
end

# RBS
class User
  attr_reader login: String
  attr_reader email: String

  def initialize: (login: String, email: String) -> void
end

一个名为**TypeProf**的新的静态类型分析器现在包含在Ruby中。 为了说明一个非常简单的例子,请考虑以下代码。

def foo
  'bar'
end

foo(12)

运行typeprof -v foo.rb,将产生以下输出,指出你向一个不接受任何参数的方法发送了一个参数。

# Errors
test.rb:5: [error] wrong number of arguments (given 1, expected 0)

# Classes
class Object
  private
  def foo: -> String
end

Ractors

Ruby的全局解释器锁(GVL)阻止了Ruby能够并行使用多个内核。 为了解决这个问题,引入了一个新的类似actor的并发原语,称为Ractor

下面是文档中的一个简单的例子,显示了消息传递是如何与ractors一起工作的。 你可以在Ractor文档中找到更多的例子。

r1, r2 = *(1..2).map do
  Ractor.new do
    n = Ractor.recv
    n.prime?
  end
end

r1.send 2**61 - 1
r2.send 2**61 + 15

p r1.take #=> true
p r2.take #=> true

向右分配

试验性地增加了对向右赋值的支持。你可以使用=> 来赋值给右边的变量,但我想不出有什么理由要使用这个赋值而不是简单的赋值。 然而,这对数组和哈希中的模式匹配值来说是很有用的。

42 => x # same as x = 42

x = { a: 1, b: 2 }

x => { b: foo }
foo #=> 2

查找模式匹配

模式匹配的语法已经被扩展到允许从数组中提取元素。 这里有一个简单的例子。

case ['a', 1, 'b', 'c', 2, 'd', 'e', 'f', 3]
in [*pre, String => x, String => y, *post]
  pre  #=> ["a", 1]
  x    #=> "b"
  y    #=> "c"
  post #=> [2, "d", "e", "f", 3]
end

无尽的方法定义

增加了新的语法,当方法主体包含一个表达式时,允许你跳过end。当你需要在代码中提取一个单行的方法时,这种简洁的语法将派上用场。

def square(x) = x * x

参数转发中的领先args

Ruby 2.7引入了带有... 语法的参数转发。然而,你可能想访问领先的参数并转发其余的参数。 现在语法已经更新,允许这样做。

def method_missing(method_name, ...)
  return nil unless method_name.in?(allowed_methods)

  object.send(method_name, ...)
end

哈希

Hash#transform_keys已经更新,接受了一个参数,让你定义哪些键应该被重命名。 你也可以传递一个块,它将被用来转换剩余的键。

note = { title: 'Ruby 3.0', created_at: '2020-12-25' }

# without block
note.transform_keys({ created_at: :created })
# => { title: 'Ruby 3.0', created: '2020-12-25' }

# with block
note.transform_keys({ created_at: 'created' }, &:to_s)
# => { 'title' => 'Ruby 3.0', 'created' => '2020-12-25' }

Hash#except在Rails中,通过ActiveSupport提供的 "新功能 "现在已经包含在语言本身中。

x = { a: 1, b: 2, c: 3 }
x.except(:c)
#=> { a: 1, b: 2 }

性能目标,又称Ruby 3x3

2015年,Matz宣布Ruby 3将比Ruby 2.0快3倍(又称3x3目标)。optcarrot基准。长期以来一直用于比较不同版本的Ruby,在启用JIT后,3.0确实达到了3倍的目标。

MJIT仍然不成熟,并不是所有的程序都能利用这个加速。 例如,Rails应用程序在启用JIT后实际上表现更差。 然而,这对CPU绑定的程序来说仍然是个好消息。 由于新引入的并发功能,这个版本最大的性能优势将在以后看到,因为更多的库会使用这些功能。