Ruby 2.7.0 已發布

我們很高興宣佈 2.7.0 發佈了。

本版帶有許多新功能及效能提升,主要有:

  • 模式匹配
  • REPL 改進
  • GC 壓縮
  • 分離依序參數和關鍵字參數

模式匹配 [實驗性質]

引入了實驗性質、在函數式程式語言廣泛使用的功能,模式匹配。見 [Feature #14912]

模式匹配可以遍歷傳入的物件,如果找到匹配的模式就賦值給指定的變數。

require "json"

json = <<END
{
  "name": "Alice",
  "age": 30,
  "children": [{ "name": "Bob", "age": 2 }]
}
END

case JSON.parse(json, symbolize_names: true)
in {name: "Alice", children: [{name: "Bob", age: age}]}
  p age #=> 2
end

進一步了解請參考 Ruby 2.7 的新功能:模式匹配

REPL 改進

irb,內建的互動環境(REPL Read-Eval-Print-Loop),透過純 Ruby 所實現的 relin 和與 readline 相容的函式庫現支持多行編輯。irb 整合了 rdoc,可以顯示任何一個類別、模組、方法之間的引用關係。 [Feature #14683][Feature #14787][Feature #14918]

除此之外,Binding#irb 所顯示的原始碼行號與查詢結果現在以彩色顯示。

Compaction GC

本版引入了 Compaction GC,可以整理零碎的記憶體空間。

由某些多線程的 Ruby 程式所引起的零碎記憶體空間,導致記憶體用量大增及速度變慢。

新增了 GC.compact 方法用來壓縮堆疊(heap)。這個方法壓縮了堆疊上正在使用的物件,進而使用更少的記憶體分頁,使堆疊對寫入式複製(CoW, copy-on-write)更加友好。 [Feature #15626]

分離依序參數和關鍵字參數

依序參數與關鍵字參數之間的自動轉換已經棄用,將在 Ruby 3 正式移除。 [Feature #14183]

詳見文章「Separation of positional and keyword arguments in Ruby 3.0」。

以下是改動的內容:

  • 當一個接受參數的方法,呼叫時傳入的最後一個參數為 Hash,但沒有傳入所須的關鍵字參數,則會出現警告訊息。 要繼續將 Hash 作為關鍵字使用的話,請使用 double splat 運算子來確保程式可在 Ruby 3 正在作動並避免警告訊息。

    def foo(key: 42); end; foo({key: 42})   # warned
    def foo(**kw);    end; foo({key: 42})   # warned
    def foo(key: 42); end; foo(**{key: 42}) # OK
    def foo(**kw);    end; foo(**{key: 42}) # OK
    
  • 當接受關鍵字參數的方法傳入關鍵字,但沒有傳入足夠的依序參數時,關鍵字會被視作最後一個依序參數並出現警告訊息。請用 Hash 傳入參數而不是關鍵字確保程式可在 Ruby 3 正在作動並避免警告訊息。

    def foo(h, **kw); end; foo(key: 42)      # warned
    def foo(h, key: 42); end; foo(key: 42)   # warned
    def foo(h, **kw); end; foo({key: 42})    # OK
    def foo(h, key: 42); end; foo({key: 42}) # OK
    
  • 當方法接受特定關鍵字,但不接受 keyword splat,傳入一個有符號及非符號為鍵的 Hash 或 keyword splat 時,Hash 仍會被分解並報一個警告訊息。請分別傳入 Hash 以確保程式可在 Ruby 3 正常作動。

    def foo(h={}, key: 42); end; foo("key" => 43, key: 42)   # warned
    def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned
    def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK
    
  • 若方法不接受關鍵字但呼叫時傳入關鍵字,則關鍵字會被依序視為 Hash 且不會出警告訊息。此行為在 Ruby 3 會繼續作動。

    def foo(opt={});  end; foo( key: 42 )   # OK
    
  • 方法接受任意關鍵字時,可以使用非符號作為關鍵字。 [Feature #14183]

    def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
    
  • 可以用 **nil 將方法標記為不接受任何關鍵字。用關鍵字呼叫這樣的方法會報一個 ArgumentError 錯誤。 [Feature #14183]

    def foo(h, **nil); end; foo(key: 1)       # ArgumentError
    def foo(h, **nil); end; foo(**{key: 1})   # ArgumentError
    def foo(h, **nil); end; foo("str" => 1)   # ArgumentError
    def foo(h, **nil); end; foo({key: 1})     # OK
    def foo(h, **nil); end; foo({"str" => 1}) # OK
    
  • 給一個不接受關鍵字的方法傳入空的 keyword splat 時,參數不再視為空 Hsah。當空 Hash 是一個必要的參數時,則會報一個警告訊息。請移除 double splat 來繼續傳入一個依序的 Hash。 [Feature #14183]

    h = {}; def foo(*a) a end; foo(**h) # []
    h = {}; def foo(a) a end; foo(**h)  # {} and warning
    h = {}; def foo(*a) a end; foo(h)   # [{}]
    h = {}; def foo(a) a end; foo(h)    # {}
    

如想不要顯示警告訊息,請使用命令行選項 -W:no-deprecated,或是添加 Warning[:deprecated] = false 這行程式碼。

其他新功能

  • 引入了基於數字的區塊參數。 [Feature #4475]

  • 引入了實驗性質的無起始範圍,可能不像無終止範圍實用,但在實作 DSL 的場景很有用。 [Feature #14799]

    ary[..3]  # identical to ary[0..3]
    rel.where(sales: ..100)
    
  • 新增 Enumerable#tally,可以算出元素出現的次數

    ["a", "b", "c", "b"].tally
    #=> {"a"=>1, "b"=>2, "c"=>1}
    
  • 現在可從 self 呼叫私有方法 [Feature #11297][Feature #16123]

    def foo
    end
    private :foo
    self.foo
    
  • 新增 Enumerator::Lazy#eager。從惰性求值的迭代器上產生一般的迭代器。 [Feature #15901]

    a = %w(foo bar baz)
    e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
    p e.class               #=> Enumerator
    p e.map {|x| x + "?" }  #=> ["FOO!?", "BAR!?", "BAZ!?"]
    

效能改進

  • JIT [實驗性質]

    • 當優化條件不成立時,經 JIT 編譯的程式碼將會重編成優化程度較低的程式碼。

    • 方法若為純方法,則進行內聯優化。這個優化是實驗性質的,目前許多方法均不是純方法。

    • --jit-min-calls 的預設值從 5 改為 10,000。

    • --jit-max-cache 的預設值從 1,000 改為 100。

  • 改變了 Fiber 的快取策略並提昇了建立 Fiber 的速度 GH-2224

  • Module#nametrue.to_sfalse.to_s 以及 nil.to_s 現在永遠回傳已經凍結的字串。同一個物件會永遠回傳相同的字串。 [實驗性質] [Feature #16150]

  • 改善了 CGI.escapeHTML 的效能 GH-2226

  • 改善了 Monitor 與 MonitorMixin 的效能 [Feature #16255]

  • 改善了(自 Ruby 1.9 以來的)Per-call-site 的方法快取命中率,從 89% 提昇至 94%。 見 GH-2583

  • RubyVM::InstructionSequence#to_binary 方法會產生執行檔,減少了執行檔的大小。 [Feature #16163]

其他自 2.6 以來的變更

  • 更新了某些標準函式庫
  • 以下函式庫不再內建,請安裝對應的 Gem 再使用。
    • CMath (cmath gem)
    • Scanf (scanf gem)
    • Shell (shell gem)
    • Synchronizer (sync gem)
    • ThreadsWait (thwait gem)
    • E2MM (e2mmap gem)
  • profile.rb 從標準函式庫移除了。

  • 將以下的函式庫納入標準函式庫
    • 同時發佈在 rubygems.org
      • benchmark
      • cgi
      • delegate
      • getoptlong
      • net-pop
      • net-smtp
      • open3
      • pstore
      • singleton
    • 只是納入了 ruby-core 但未發佈在 rubygems.org
      • monitor
      • observer
      • timeout
      • tracer
      • uri
      • yaml
  • 對沒有區塊的 Proc.newproc 方法,用區塊呼叫會報一個警告訊息。

  • 對沒有區塊的 lambda 的方法,用區塊呼叫則會拋一個異常。

  • 更新 Unicode version and Emoji version 從 11.0.0 至 12.0.0。 [Feature #15321]

  • 更新 Unicode version 至 12.1.0,支援方塊版的令和新年號(U+32FF)。 [Feature #15195]

  • Date.jisx0301Date#jisx0301Date.parse 現可以解析日本新年號 [Feature #15742]

  • 需使用支援 C99 的編譯器 [Misc #15347]

了解更多請參考新聞提交紀錄

以上自 2.6.0 以來,計 4190 檔案變更,227498 行新增(+),99979 行刪減(-)

耶誕快樂、佳節愉快,享受與 Ruby 2.7 一起寫程式的時光!

下載

  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2

    SIZE: 14703381
    SHA1: b54f4633174dbc55db77d9fd6d0ef90cc35503af
    SHA256: 7aa247a19622a803bdd29fdb28108de9798abe841254fe8ea82c31d125c6ab26
    SHA512: 8b8dd0ceba65bdde53b7c59e6a84bc6bf634c676bfeb2ff0b3604c362c663b465397f31ff6c936441b3daabb78fb7a619be5569480c95f113dd0453488761ce7
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.gz

    SIZE: 16799684
    SHA1: 6f4e99b5556010cb27e236873cb8c09eb8317cd5
    SHA256: 8c99aa93b5e2f1bc8437d1bbbefd27b13e7694025331f77245d0c068ef1f8cbe
    SHA512: 973fc29b7c19e96c5299817d00fbdd6176319468abfca61c12b5e177b0fb0d31174a5a5525985122a7a356091a709f41b332454094940362322d1f42b77c9927
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.xz

    SIZE: 11990900
    SHA1: 943c767cec037529b8e2d3cc14fc880cad5bad8d
    SHA256: 27d350a52a02b53034ca0794efe518667d558f152656c2baaf08f3d0c8b02343
    SHA512: dd5690c631bf3a2b76cdc06902bcd76a89713a045e136debab9b8a81ff8c433bbb254aa09e4014ca1cf85a69ff4bcb13de11da5e40c224e7268be43ef2194af7
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.zip

    SIZE: 20571744
    SHA1: fbebdd3a2a641f9a81f7d8db5abd926acea27e80
    SHA256: 8bf2050fa1fc76882f878fd526e4184dc54bd402e385efa80ef5fd3b810522e0
    SHA512: 5060f2dd3bfd271ef255b17589d6d014260d7ec2d97b48112b717ee01c62fe125c3fe04f813e02d607cea3f0a2a812b14eb3a28d06c2551354dfeff5f4c3dd6b
    

Ruby 是

Ruby 最早由 Matz(松本行弘)於 1993 年開發,現在開發由開源社群所維護。Ruby 可以在多個平台上運行,廣受世人喜愛用於開發網路應用。