Ruby 2.6 新特征介绍
Ruby 2.6在圣诞节那天发布, 并带来了一些有趣的新函数。 以下是更改内容的快速摘要。 和我以前版本的摘要一样 ( 2.5 , 2.4 , 2.3 ) 我只是总结一下 我觉得最有趣的函数。 有关更改的完整列表, 看看 更改日志。
Endless ranges
引入了新的语法以表示无限范围。 在case语句中匹配范围时,这将很有用。
case n
when 1..9 then 'Single digit'
when 10..99 then 'Two digit'
when 100.. then 'Three or more'
end
以前,(1 ..)
将表示为(1..Float ::INFINITY)
。
Proc,lambda和Method
#>>
和 #<<
方法已添加到 Proc
和Method
对象中,以允许将它们组成一个新方法。
square = -> (n) { n * n }
add_2 = -> (n) { n + 2 }
(square >> add_2).call(5) #=> 27
(square << add_2).call(5) #=> 49
使用 #>>
操作,数字将首先平方,然后对第一个proc调用的结果执行 add_2
。在 #<<
的情况下,调用proc的顺序相反。
我希望我们没有两种不同的proc编写方式,而只使用 #>>
。但是合成是Ruby的重要补充,它将使我们能够以更具函数性的风格进行编写。
Kernel#then
这不是新函数, 但是Kernel#yield_self
的别名 是Ruby 2.5中引入的 并允许我们进行连锁经营 进入这样的管道:
isbn = '978-1-93778-549-9'
isbn.gsub('-', '')
.then { |isbn| URI("#{API_URL}?q=isbn:#{isbn}") }
.then { |uri| Net:HTTP.get(uri) }
.then { |json_response| JSON.parse(json_response) }
.then { |response| response.dig('items', 'volumeInfo') }
Enumerable#chain
and Enumerator#+
这会返回一个 Enumerator ::Chain
对象, 它可以作为单个枚举器使用。
(1..3).chain((5..7), [9, 10]).to_a
#=> [1, 2, 3, 5, 6, 7, 9, 10]
list = (1..3).each + (5..7) + (9..10)
list.to_a
#=> [1, 2, 3, 5, 6, 7, 9, 10]
合并多个哈希
Hash#merge
仅接受了一个参数,直到2.5。 合并两个以上哈希的唯一方法 是将呼叫链接到#merge
。 现在,您可以将多个哈希传递给该方法。
foo = { a: 1 }
bar = { b: 2 }
baz = { c: 3 }
foo.merge(bar, baz) #=> { a: 1, b: 2, c: 3 }
# ruby 2.5
# foo.merge(bar).merge(baz)
Array#union
and Array#difference
这些方法的工作原理与 |
和 &
运算符。不同之处在于它们可以接受多个参数并且更易于链接。
a = [1, 1, 2, 3]
b = [3, 4]
a.union(b) #=> [1, 2, 3, 4]
a.difference(b) #=> [1, 1, 2]
Enumerable#to_h
现在,Enumerable#to_h
接受了一个将键映射到值的块。 这使我们能够转换散列 无需使用map
创建中间数组, 或使用 reduce
语法。
hash = { foo: 2, bar: 3 }
hash.to_h { |k, v| [k.upcase, v*v] } #=> { FOO: 4, BAR: 9 }
# ruby 2.5:
# hash.map { |k, v| [k.upcase, v*v] }.to_h
# hash.reduce({}) { |result, (k, v)| result.merge(k.upcase => v) }
Enumerator::ArithmeticSequence
Enumerator
的子类 被介绍来代表 通过调用Step
创建的对象 在Range
和Numeric
对象上。 这使得做类似的事情成为可能 检查序列是否相等。
r1 = (1..10).step(2)
r2 = (1..10).step(2)
r1 == r2 #=> true if 2.6, false in 2.5
1.step == (1..).step #=> true
Range
变化
%
运算符 已作为step
的别名添加。 因此(1..10)%2
等效于(1..10).step (2)
。
(a..b).cover?(x)
检查 a <= x < b
,而 (a..b).include?(x)
遍历该范围并检查是否有任何元素等于x。这使我们可以执行以下操作:
case DateTime.now
when Date.today..Date.today+1
puts 'matched'
else
puts 'not matched'
end
注意: 在本文的早期版本中, 我在示例中使用了字符串范围。 为了向后兼容, 字符串范围的行为没有改变。
('a'..'c').cover?('bb') #=> true
('a'..'c').include?('bb') #=> false
case 'bb'
when 'a'..'c' then 'matched'
else 'not matched'
end
#=> 'not matched'
Kernel exception 关键字
Exception
关键字参数 为某些Kernel
方法像Integer
,Float
和System
。 对于Numeric
方法, 我们现在可以传递Exception:false
为了避免在解析无效值时加注, 并返回 nil
。
另一方面Kernel#system
, 接受exception:true
如果命令以非零退出状态退出 (而不是返回false
) 或者命令执行失败 (而不是返回nil
)。
Integer('foo', exception: false) #=> nil
Float('foo', exception: false) #=> nil
system('foo', exception: true) #=> exception
性能提升
性能方面的最大新闻 是一个JIT实现, 叫 MJIT , 被合并为Ruby。 可以启用 使用-jit
标志。
MJIT导致微基准测试的加速, 但还不够成熟 在较大的代码库(如Rails应用程序)中工作。 对于Rails,它甚至比非JIT版本慢。
但是,这是重要的一步 朝着Ruby 3x3目标迈进, 就是让Ruby 3 至少比Ruby 2.0快3倍。 目前,带有JIT的Ruby 2.6是 比2.0快近2.5倍 在Optcarrot基准测试中, 使用哪个 比较性能 Ruby版本 3x3的目标。
除此之外, 第二个垃圾收集堆, 称为瞬时堆, 被介绍了 减少内存使用 并提高了GC速度 寿命短的物体 Proc.call
和 block.call
其他变化
- flip flop 运算符最终被弃用, 并可能会在Ruby 3中删除。
- Bundler现在是默认gem, 因此您不再需要
gem安装捆绑程序
安装Ruby之后。 Rubygems 3.0.1也被合并到Ruby中。 - 添加了
Array#filter
作为#select
的别名。 - 先前版本的ruby警告 如果您在
begin
块中有一个else
子句 没有rescue
。 这将在2.6中导致语法错误。
begin
puts 'begin'
else
puts 'else'
end
# Ruby 2.6
#=> foo.rb:5: else without rescue is useless
# Ruby 2.5
#=> foo.rb:7: warning: else without rescue is useless
#=> begin
#=> else
链接:https://www.learnfk.com/article-ruby-2-6-features
来源:Learnfk无涯私塾网