Ruby 2.0 有哪些新特性?

jopen 11年前發布 | 8K 次閱讀 Ruby

本月 24 日 Ruby 2.0 終于就要發布了。

        Ruby 核心團隊的卜部昌平桑昨天在一個內部學習會上的 presentation,介紹了 Ruby 2.0 所包含的一些新特性。

        (本文內容選譯自該幻燈片。)

Ruby 2.0 有哪些新特性?

        為什么有 Ruby 2.0?

  • 因為我們在改變事物。

  • 我們渴望讓自己變得越來越快樂、健康、以及高產。

  • 不必畏懼。“擁抱變化。”

        Ruby 2.0 有什么新鮮的?

        什么不是 Ruby 2 中的新鮮貨

  • 幾乎所有的東西。

  • “100% 后向兼容”,matz 如是說。

  • 在現實中……
  • (舉個例子來說)Rails 仍然能完好運行如初。

        也就是說,

  • 新的東西被加進來了。

  • 許多內部的東西得到了改進。

        Ruby 2.0 的新句法

        關鍵字參數(Keyword arguments)

        下面的代碼在 1.x 中能夠正常工作:

obj.method "with", :lots => "of",
                   :args => "in",
                   :hash => "form"

        但是,問題出在哪呢?

        問題是在定義該方法的時候: (Mort 注:在 Ruby 1.x 中,只能將多個帶符號名稱的參數作為一個 Hash 來傳遞給方法。要為參數指定默認值,實現起來就很累贅,參見如下代碼)

def obj.method (arg, hash)
  lots = Hash[:lots] || "default"   args = Hash[:args] || "another"   
  hand = Hash[:by hand] || "annoying"   ...end

        注意到代碼中錯誤的Hash[:by hand]——手寫代碼是錯誤產生的根源!

        從 2.0 開始,Ruby 將引入關鍵字參數:

def obj.method (a, b = 1, c: 1, d: 2)

        其中a為固定參數,b為可選參數,cd則為關鍵字參數。這樣,局部變量abcd都將被恰當地賦值。

        在調用函數時,原有的調用方式無需更改。

        Mort 注:雖然幻燈片里沒有寫,傳統的基于 Hash 參數的調用方法是這個樣子的

obj.method ("foo", :c => 2, :d => 3)

        現在 Ruby 2.0 同時也支持直接采用關鍵字參數的調用方法:(Python 程序員一定會覺得這種語法更親切)

obj.method ("foo", c: 2, d: 3)

        更詳細的示例,可以參考這里:http://brainspec.com/blog/2012/10/08/keyword-arguments-ruby-2-0/

        其他細微的句法改進

  • 引入了符號數組字面值%i%I
%i(foo bar baz) # => [:foo, :bar, :baz]
  • Ruby 現在默認把所有的輸入都視作 UTF-8 編碼。當然你也可以顯式地指定需要的編碼。

        Ruby 2.0 的核心性能改進

        require的改進

  • 背景:今天,由于我們有了許多 gems,啟動 Ruby 有時甚至需要一次 require 128+ 個庫——這帶來了糟糕的性能問題。

  • 解決:require變得更快了(從計算復雜度的意義上來說)。

  • 若干技術被應用于減少多余的計算上。

        Backtrace 惰性生成

  • 起初,backtraces 只是字符串數組而已。

  • 每當拋出異常時,這些字符串就被自上而下地生成出來,即使在它們沒有實際用途的情況下。

  • 這導致了超乎尋常的低效,尤其是當你有 1024+ 個 stack frames 時(這在 Rails 應用中很常見)。
  • 從 Ruby 2.x 開始,Thread::Backtrace被用來取代字符串。

  • 它們非常地輕量級。
  • 當你需要查看 backtrace 時,只需將它們轉換成字符串即可(調用#to_s)。

        Flonum 類

  • 在 64 位平臺(如今早就爛大街了)上,指針,整型和浮點型數均是 64 位寬度的。

  • 在 Ruby 中,指針和整型均為C級別的register寄存器變量。而double卻是存儲在內存中的,如果我們能夠如操作指針一樣操作它們,將如何呢?

  • 問題:如何讓一個指針和一個 double 共存于一個 union 中?

  • 解決:一些技巧性的位移。

        Mort 注:圖片懶得搬運了……請參見原幻燈片。

        GC(Garbage Collection)

  • Bitmap 標志:以前,GC 標志位存儲于每個對象中,但現在已經被轉移到了專用的內存頁中,以減少緩存的誤查詢(同時也更加 CoW (Copy-on-Write)友好)。

  • 非遞歸標志:標志函數如今避免了機器棧溢出的風險。

  • 惰性清理(從 1.9.3 起):清理器只有在必須的地方才進行收集(減少了 stop 時間)。

        Ruby 2.0 的新核心特性:#1 調試工具

        DTrace 支持

        TracePoint 支持

        GC stats

        Ruby 2.0 的新核心特性:#2 核心庫

        細粒度的異步中斷處理

        Ruby 的執行有時會因為各種原因而中斷,例如,超時。

        Ruby 2.0 提供了細粒度的異步中斷處理方案:

Thread.async_interrupt_timing Timeout::Error => :defer do   timeout (rand ()) do     
begin
      Thread.async_interrupt_timing Timeout::Error => :immediate do         setup
        handle
        ...
      end     ensure
      teardown
    end end end

        模塊前插

        有時候你想要給一個方法添加需要的安裝或拆解代碼,而相應的部分卻定義在別處。

module ActiveRecordHelper
  def save
    ???
  end end

        該如何去做呢?在 Ruby 2.0 中,你可以:

class Foo < AR::Base
  prepend AR::Helper

  def save
    bar
  end end module AR::Helper
  def save
    foo
    super
    baz
  end end  
Foo.new.save

        這避開了 Rails 中的所謂“別名方法鏈(alias method chain)”的困擾。AMC 什么的已經不再必要了。

        惰性枚舉器

        Ruby 的foo.bar.baz. ...風格(所謂的“流水作業”)有時會傳遞許多并不必要的臨時對象,而這些理論上都可以通過惰性求值來避免。

File.open (path) {|fp|
    fp.each_line. \
    select {|line| # 生成了臨時數組
    /regexp/ =~ line
    }. \
    each_with_index.map {|line, no| # 生成了臨時數組
    sprintf ("%d: %s\n", no, line)
    }. \
    first (10) .each {|str| # 生成了臨時數組
        puts (str)
    }
}

        -

File.open (path) {|fp|
    fp.each_line.lazy \
    select {|line| # 沒有臨時數組產生
    /regexp/ =~ line
    }. \
    each_with_index.map {|line, no| # 沒有臨時數組產生
    sprintf ("%d: %s\n", no, line)
    }. \
    first (10) .each {|str| # 沒有臨時數組產生
        puts (str)
    }
} # 甚至在到達 EOF 之前都不讀取數據

        一個有趣的應用實例:無窮枚舉器。

# Leibniz formula for π
(..Float::INFINITY) .lazy.map {|i|
    ((-1) ** i) / (2*i + 1) .to_f
}.take (65536) .reduce (:+) * 4

        其他的新方法

  • Kernel.__dir__:獲取__FILE__所在的目錄名。
  • Kernel#to_h:通用的 Hash 轉換方法。
  • Random類(1.9+):可重復的 PRNG。
  • IO#wait_writable:等待直到可寫。
  • Refinements: 實驗性的。

        Mort 注:更多關于 Ruby 2.0 核心特性的介紹,參考

        Ruby 2.0 標準庫的改進

  • CGI
  • CGI 已經為 HTML5 做好了一切準備。
  • net/http
  • 支持 SNI(Server Name Indication)。
  • Zlib 綁定
  • Zlib 如今運行在解釋器的進程鎖之外。這意味著 zlib 在多線程的情形下運行速度將更快。
  • 更新的 stdlibs(標準庫)
  • Rubygems 2.0.0
  • JSON 1.7.7
  • Rake 0.9.5
  • Rdoc 4.0
  • 以及其它(REXML,yaml,openssl……)

        總結

        什么不是 Ruby 2 中的新鮮貨

  • 幾乎所有的東西!
  • “100% 后向兼容”,matz 如是說。
  • (舉個例子來說)Rails 仍然能完好運行如初。
  • 不必畏懼!開始使用 2.0.0 版吧!

        也就是說,

  • 新的東西被加進來了。
  • 許多內部的東西得到了改進。
  • 即使你對你當前的環境充分自信,2. 0.0 仍然值得你擁有。

        Don’t be afraid. Use Ruby today!

        視頻:http://jpopsuki.tv/video/AKB48—Ruby/eb57d9ad12c4f7a324fc6854f673d40d (AKB48 演唱)

來自: www.soimort.org

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!