Ruby 1.9: It works!
[email protected] 2009/4/18 OSDC.TW
2009年4月19日星期日
Ruby 1.9: It (must) works!
[email protected] 2009/4/18 OSDC.TW
2009年4月19日星期日
我是誰? • 張文鈿 a.k.a. ihower • •
http://ihower.idv.tw/blog/
• •
http://handlino.com
http://twitter.com/ihower
• 從 2006 年開始使用 Ruby • 和多(股)公司 Rails Developer
2009年4月19日星期日
http://registrano.com
Agenda • Overview • What’s changed? • What’s New? • Ruby 1.9 on Rails
(External Interater, M17N, The Threading Model)
2009年4月19日星期日
1. Overview
2009年4月19日星期日
Ruby 1.8.6 廣為使用的版本
• Ruby 1.8.6, release at 2007/3/12 • Stable • Performance sucks • Memory leaks • NewRelic Report 69.4% 使用率
http://railslab.newrelic.com/2009/04/01/the-state-of-the-stack-a-ruby-on-rails-benchmarking-report
2009年4月19日星期日
Ruby 1.8.7 敬而遠之的版本
• Ruby 1.8.7 release at 2008/5/31 • 移植了部份 1.9 的功能 • gems, library 相容性變差 • JRuby 跳過 1.8.7 不實做 • NewRelic Report 14.5% 使用率
(與1.8.6不完全相容)
2009年4月19日星期日
Ruby 1.9 尚待推廣的版本
• Ruby 1.9.0 release development version in 2007/12/25
• Ruby 1.9.1 release stable/production version in 2009/1/30
• Better performance • Better encoding support 2009年4月19日星期日
Ruby Implementations 能上 production 的
• • • • 2009年4月19日星期日
Ruby 1.8.6, 1.8.7 (MRI, Matz’ Ruby Interpreter)
•
EngineYard 將接手維護 1.8.6,預計將帶入 MBARI 的 GC patch http://www.infoq.com/news/2009/01/ruby-patches-fix-leaks
Ruby 1.9.1 (YARV) JRuby • 相容 Ruby1.8.6 語法,最新版涵蓋 1.9 功能。 Ruby Enterprise Edition(REE) • 衍生自 Ruby 1.8.6,但是大修 GC,改善 memory leak 問題
Ruby Implementations 還不能上 production 的
• MacRuby (based on Objective-C) • Rubinius (Engine yard project) • MagLev (based on smalltalk) • IronRuby (based on Microsoft .NET) • Cardinal (based on Parrot VM) 2009年4月19日星期日
Performance
(平均比 1.8 快 2~2.5 倍)
http://antoniocangiano.com/category/ruby-benchmark-suite/ http://github.com/acangiano/ruby-benchmark-suite/
2009年4月19日星期日
Ubuntu : Intel® Q6600® quad-core Computer Language Benchmarks Game
http://shootout.alioth.debian.org/
2009年4月19日星期日
2. What’s changed?
2009年4月19日星期日
Ordered Hash 會照順序排 { :a => 1, :b=> 2, :c => 3 }.merge( :d => 4 )
2009年4月19日星期日
1.8
{:a=>1, :d=>4, :b=>2, :c=>3}
1.9
{:a=>1, :b=>2, :c=>3, :d=>4}
new Hash literal 新的雜湊語法
1.8,1.9
config = { :foo => 1234, :bar => 6789 } Person.find(:all, :conditions => { :name => 'ihower' } )
1.9
config = { foo: 1234, bar: 6789 } Person.find(:all, :conditions => { name: 'ihower' } )
2009年4月19日星期日
Hash syntax 不允許用逗號取代 =>
2009年4月19日星期日
1.8
{1,2,3,4} => {1=>2, 3=>4}
1.9
{1,2,3,4} => syntax error, unexpected ',', expecting tASSOC
Hash#select hash = { :a => 1, :b => 2, :c => 3 } hash.select{ |k, v| v > 1 }
2009年4月19日星期日
1.8
[[:b, 2], [:c, 3]]
1.9
{:b=>2, :c=>3}
Array#to_s, Hash#to_s 1.8
2009年4月19日星期日
1.9
[1,2,3,4].to_s => "1234"
[1,2,3,4].to_s => "[1, 2, 3, 4]"
{1=>2,3=>4}.to_s => "1234"
{1=>2,3=>4}.to_s => "{1=>2, 3=>4}"
case syntax 移除冒號用法 name = case when x == 1 : "one" 1.8 when x == 2 : "two" else "many" end
name = case when x == 1 then "one" 1.8,1.9 when x == 2 then "two" else "many" end
2009年4月19日星期日
name = case when x == 1 1.8,1.9 "one" when x == 2 "two" else "many" end
block’s parameter always local 區塊參數必是 local 變數 x = "foo" y = "bar" [1,2,3].each do |x| y=x+1 end
1.8
2009年4月19日星期日
[x,y] => [3, 4]
1.9
[x,y] => ["foo", 4]
block’s parameter always local 區塊參數必是 local 變數 x = "foo" y = "bar" [1,2,3].each do |x| y=x+1 end
1.8
[x,y] => [3, 4]
造成必須小心命名避免 蓋掉外面的變數
2009年4月19日星期日
1.9
[x,y] => ["foo", 4]
block-local variable 明確宣告區塊內的變數是 local
1.8,1.9
bar = "ihower" [1,2,3].each do |val| foo = val bar = val end foo
# NameError: undefined local variable or method `foo’
bar => 3
2009年4月19日星期日
1.9
bar = "ihower" [1,2,3].each do |val; bar| bar = val end bar => "ihower"
block-local variable 明確宣告區塊內的變數是 local
1.8,1.9
bar = "ihower" [1,2,3].each do |val| foo = val bar = val end foo
# NameError: undefined local variable or method `foo’
bar => 3
2009年4月19日星期日
1.9
bar = "ihower" [1,2,3].each do |val; bar| bar = val end bar => "ihower" 可避免 bar 變數被蓋掉
block can accept block argrments 區塊參數列亦可使用區塊變數 proc1 = lambda do |a, *b, &block| p a p b p c block.call end proc1.call(1,2,3,4) { puts "in block1" } # 輸出 1 [2,3,4] "in block1"
2009年4月19日星期日
new lambda literal 新的 lambda 語法
1.8,1.9
lambda { |a| a*3 }.call(4) # => 12
1.8,1.9
lambda { |a| a*3 }[4] # => 12
1.9
2009年4月19日星期日
->(a) { a*3 }.(4) # => 12
def my_if(condition, then_clause, else_clause) if condition then_clause.call else else_clause.call end end 5.times do |val| my_if (val < 3), -> { puts "#{val} is small" }, -> { puts "#{val} is big" } end # 0 1 2 3 4
2009年4月19日星期日
輸出 is small is small is small is big is big
def my_while(cond, &body) while cond.call body.call end end a = 0 my_while -> { a < 3 } do puts a a += 1 end # 輸出 0 1 2
2009年4月19日星期日
Kernel.proc 大地雷, do not use it!
• proc 等同於 lambda 1.9 • proc 修正成 Proc.new 1.8
2009年4月19日星期日
BasicObject 新的繼承體系 root
1.8,1.9
Class.superclass.superclass => Object
1.8
Class.superclass.superclass.superclass => nil
1.9
Class.superclass.superclass.superclass => BasicObject BasicObject.superclass => nil BasicObject.instance_methods => [:==, :equal?, :!, :!=, :instance_eval,
:instance_exec, :__send__]
可用在 metaprogramming 時 的 blank canvas
2009年4月19日星期日
standard library changes • + Rubygems •
no longer needed require ‘rubygems’
•
no longer gem install rake
• + Rake • ~ Test::Unit replaced by MiniTest • - soap, jcode...etc, some rarely used, old libraries
2009年4月19日星期日
3. What’s new?
2009年4月19日星期日
External Iterator
2009年4月19日星期日
Iterators
建立外部迭代子 to_enum 1.8,1.9
Internal
arr = [ 1, 2, "ihower" ] arr.each do |a| puts a end # => 1 # => 2 # => "ihower"
2009年4月19日星期日
1.9
External
arr = [ 1, 2, "ihower" ] enum_a = arr.to_enum # 建立 Enumerators 物件 (預設用each) enum_a.next # => 1 enum_a.next # => 2 enum_a.next # => "ihower"
Enumerators 更多範例 1.9 h = { foo: "567", bar: "890" } enum_h = h.to_enum enum_h.next # => [:foo, "567"] enum_h.next # => [:bar, "890"]
2009年4月19日星期日
1.9 arr = [ 1, 2, "ihower" ] enum_a = arr.to_enum(:each_with_index) enum_a.next # => [1, 0] enum_a.next # => [2, 1] enum_a.next # => ["ihower", 2]
StopIteration exception 同時迭代數個物件 1.9
short_enum = [1, 2, 3].to_enum long_enum = ('a'..'z').to_enum loop do puts "#{short_enum.next} #{long_enum.next}" end # => 1-a # => 2-b # => 3-c
2009年4月19日星期日
StopIteration exception 同時迭代數個物件 1.9
short_enum = [1, 2, 3].to_enum long_enum = ('a'..'z').to_enum loop do puts "#{short_enum.next} #{long_enum.next}" end # => 1-a # => 2-b # => 3-c
2009年4月19日星期日
用完時丟出 StopIteration 例外
Enumerator from iterator 亦可從 iterator method 建立 1.9 arr = [ 1, 2, "ihower" ] enum_a = arr.each # 使用迭代子函式來建立 Enumerator 物件 enum_a.next # => 1 enum_a.next # => 2 enum_a.next # => "ihower"
2009年4月19日星期日
Enumerators.new 使用 code block 手動建立
1.9
seq = Enumerator.new do |yielder| n1 = 0 n2 = 1 回傳值並在此暫停 loop do 無窮迴圈 n3 = n1 + n2 yielder.yield n3 n1 = n2 n2 = n3 end end seq.next # 1 seq.next # 2 2.times { puts seq.next } # 3 # 5
2009年4月19日星期日
Enumerator objects are also enumerable 1.9
seq.first(10) # => [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] seq.to_a # Don’t do this if your Enumerator has infinite elements
2009年4月19日星期日
M17N (Multilingualization)
2009年4月19日星期日
In Ruby 1.8, a String is always just a collection of bytes
2009年4月19日星期日
Ruby 1.8 String fails 1.8
>> "中文".reverse => "\207\226歸\344" >> "中文".size => 6
2009年4月19日星期日
Ruby 1.8 Regexp 有支援 UTF-8
• Support None (n or N), EUC (e or E), Shift_JIS (s or S), UTF-8 (u or U) 1.8,1.9
2009年4月19日星期日
>> "中文".scan(/./u) => ["中", "文"]
Use Regexp to handle String 使用 Regexp 拯救字串處理
1.8,1.9
>> "中文".scan(/./u).reverse.join => "文中" >> "中文".scan(/./u).size => 2
2009年4月19日星期日
$KCODE = “U” or ruby -KU
• 變更 regular expressions 的 default encoding • $KCODE = "U" 也可以讓 terminal 正確顯示 1.8
2009年4月19日星期日
>> => >> >> =>
"中文" "\344\270\255\346\226\207" $KCODE='u' "中文" "中文"
Unicode codepoint
另一種在 Ruby 1.8 拯救 UTF-8 字串的方式 1.8,1.9
>> "中文".unpack("U*") => [20013, 25991] >> "中文".unpack("U*").reverse.pack("U*") => "文中" >> "中文".unpack("U*").size => 2
2009年4月19日星期日
Unicode codepoint(cont.) Rails ActiveSupport 使用這個技巧
1.8,1.9
>> "中文".chars # in Rails => #
>> "中文".chars.size => 2
2009年4月19日星期日
iconv library 處理非 UTF-8 data
• • • •
2009年4月19日星期日
C Library, it’s fast. convert your encoding to UTF-8 handle it export back to your encoding
jcode library too simple, not useful
1.8
$KCODE = 'UTF8' require 'jcode' str = "中文" str.size # 9 str.jsize # 2
2009年4月19日星期日
No enough encodings supported in Ruby 1.8
• String 沒有 Encoding 機制 • Regexp 支援不夠全面 • •
一直加 encoding 支援並不是辦法,總會用完 Regexp letter
•
String, IO object, program source 可能都不同
也不能簡單解決其他問題,例如處理 #String.upcase、encoded data 是否 valid?
• $KCODE 是全域變數
2009年4月19日星期日
pick one encoding, likely Unicode, and works all data in one format? No.
Ruby 1.9 make it possible to work with data with 83 encoding.
2009年4月19日星期日
>> Encoding.name_list => ["ASCII-8BIT", "UTF-8", "US-ASCII", "Big5", "CP949", "Emacs-Mule", "EUC-JP", "EUC-KR", "EUC-TW", "GB18030", "GBK", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "KOI8-R", "KOI8-U", "Shift_JIS", "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE", "Windows-1251", "BINARY", "IBM437", "CP437", "IBM737", "CP737", "IBM775", "CP775", "CP850", "IBM850", "IBM852", "CP852", "IBM855", "CP855", "IBM857", "CP857", "IBM860", "CP860", "IBM861", "CP861", "IBM862", "CP862", "IBM863", "CP863", "IBM864", "CP864", "IBM865", "CP865", "IBM866", "CP866", "IBM869", "CP869", "Windows-1258", "CP1258", "GB1988", "macCentEuro", "macCroatian", "macCyrillic", "macGreek", "macIceland", "macRoman", "macRomania", "macThai", "macTurkish", "macUkraine", "CP950", "stateless-ISO-2022-JP", "eucJP", "eucJP-ms", "euc-jp-ms", "CP51932", "eucKR", "eucTW", "GB2312", "EUC-CN", "eucCN", "GB12345", "CP936", "ISO-2022JP", "ISO2022-JP", "ISO-2022-JP-2", "ISO2022-JP2", "ISO8859-1", "Windows-1252", "CP1252", "ISO8859-2", "Windows-1250", "CP1250", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "Windows-1256", "CP1256", "ISO8859-7", "Windows-1253", "CP1253", "ISO8859-8", "Windows-1255", "CP1255", "ISO8859-9", "Windows-1254", "CP1254", "ISO8859-10", "ISO8859-11", "TIS-620", "Windows-874", "CP874", "ISO8859-13", "Windows-1257", "CP1257", "ISO8859-14", "ISO8859-15", "ISO8859-16", "CP878", "SJIS", "Windows-31J", "CP932", "csWindows31J", "MacJapanese", "MacJapan", "ASCII", "ANSI_X3.4-1968", "646", "UTF-7", "CP65000", "CP65001", "UTF8-MAC", "UTF-8-MAC", "UCS-2BE", "UCS-4BE", "UCS-4LE", "CP1251", "locale", "external", "internal"]
2009年4月19日星期日
All String are Encoded • In Ruby 1.9 a String is a collection of encoded characters.
除了 raw bytes,還包括 Encoding 資訊。 1.9
>> "中文".encoding.name => "UTF-8" Encoding object
2009年4月19日星期日
String works in characters 1.9
>> "中文".reverse => "文中" >> "中文".size => 2 >> "中文".bytesize => 6
2009年4月19日星期日
String Indexing 1.9
1.8 >> "abc"[0] => 97
>> "abc"[0] => "a"
>> "中文"[1] => 184
>> "中文"[1] => "文" >> "abc"[0].ord => 97
2009年4月19日星期日
萬歲!
In Ruby 1.9, String has attached Encoding object, and works in characters.
2009年4月19日星期日
Transcoding 改變編碼 1.9
utf8 = "測試" utf8.bytesize # 6 utf8.bytes.to_a # [230, 184, 172, 232, 169, 166] big5 = utf8.encode("big5") big5.encoding.name # ”Big5” big5.bytesize # 4 big5.bytes.to_a # [180, 250, 184, 213]
2009年4月19日星期日
Transcoding fails 轉碼失敗 1.9
str = "Résumé" str.encode("big5") => Encoding::UndefinedConversionError: "\xC3\xA9" from UTF-8 to Big5 from (irb):2:in `encode' from (irb):2 from /usr/local/bin/irb19:12:in `<main>'
2009年4月19日星期日
Force Transcoding 改變編碼,但不改 byte data
1.9
utf8 = "測試" big5 = utf8.encode("big5") big5.valid_encoding? => true big5.force_encoding("utf-8") big5.valid_encoding? => false
2009年4月19日星期日
Force Transcoding fails 編碼不對無法進一步操作 1.9
big5.valid_encoding? # false big5 =~ /123456/ => ArgumentError: invalid byte sequence in UTF-8 from (irb):11 from /usr/local/bin/irb19:12:in `<main>'
2009年4月19日星期日
Encoding.compatible? 例如: ASCII with a bigger Encoding
1.9
ascii = "my ".force_encoding("ascii") utf8 = "Résumé" # 檢查相容性 Encoding.compatible?(ascii, utf8) #<Encoding:UTF-8> # 相加 my_resume = ascii + utf8 puts my_resume puts my_resume.encoding.name
2009年4月19日星期日
# "My Résumé" # UTF-8
Encoding.compatible? 不相容不能加在一起 1.9
big5 = "測試".encode("big5") utf8 = "Résumé" # 檢查相容性 Encoding.compatible?(big5, utf8)
# nil
# 相加 big5 + utf8 => Encoding::CompatibilityError: incompatible character encodings: Big5 and UTF-8 from (irb):25 from /usr/local/bin/irb19:12:in `<main>'
2009年4月19日星期日
String Iteration each 被移除了
• Strings are no longer enumerable • Ruby 1.8 each() has been removed 1.9 • Ruby 1.9 use explicit iterator • each_line • each_byte • each_char • each_codepoint 2009年4月19日星期日
What’s default encoding? 疑? 那預設的 encoding 是什麼?
2009年4月19日星期日
program source encoding 放在檔案開頭的 magic comment
# encoding: UTF-8 或 #!/usr/bin/env ruby -w # encoding: UTF-8 或 # coding: UTF-8 或 # -*- coding: UTF-8 -*-
2009年4月19日星期日
program without magic comment 如果沒有指定編碼
ruby foobar.rb # US-ASCII ruby -e foobar.rb 或用 irb # 會看 OS 的語系設定
($LC_CTYPE, $LANG)
ruby -KU foobar.rb # UTF-8,與 Ruby 1.8 相容的指令
2009年4月19日星期日
如果程式碼中有不符合 program source encoding 的字元,程式執行會 error
invalid multibyte char (US-ASCII)
2009年4月19日星期日
IO Object 讀檔案 1.9
這是一個 大五碼檔案 # encoding: utf-8 f = File.open("big5.txt","r:big5") puts f.external_encoding # Big5 puts f.gets.encoding # Big5
2009年4月19日星期日
IO Object 讀檔案並自動轉碼 1.9 # encoding: utf-8 f = File.open("big5.txt","r:big5:utf-8") puts f.external_encoding # Big5 puts f.internal_encoding # UTF-8 puts f.gets.encoding # UTF-8
2009年4月19日星期日
IO Object 寫檔案 1.9 # encoding: utf-8 f = File.open("another_big5.txt", "w:big5") puts f.external_encoding # Big5 data = "中文字" puts data.encoding.name # UTF-8 f << data
2009年4月19日星期日
IO Object 寫檔案 1.9 # encoding: utf-8 f = File.open("another_big5.txt", "w:big5") puts f.external_encoding # Big5 data = "中文字" puts data.encoding.name # UTF-8 f << data
寫入大五碼
2009年4月19日星期日
Regexp has encoding too 1.9 /\w/.encoding => #<Encoding:US-ASCII> /中文/.encoding => #<Encoding:UTF-8>
2009年4月19日星期日
• Oniguruma engine • Same basic API • better performance • support for a lot of encoding • extended syntax http://www.geocities.jp/kosako3/oniguruma/
Default Encoding Overview
• String literal 按照 program source 編碼 • Symbols 和 Regexp 如果只有用到 7-bit,會是
US-ASCII,不然則按照 program source 編碼。
• IO 物件的 external_encoding 按照 OS 語系設定 • •
2009年4月19日星期日
或使用 ruby -E 指定編碼 或設定 Encoding.external_encoding
The Threading model
2009年4月19日星期日
Fibers 協同常式 (semi-coroutine)
一種可以多次進出 code block 的控制結構
2009年4月19日星期日
1.9
f = Fiber.new { 2.times do puts "Fiber say hi" Fiber.yield # 將控制權轉回呼叫者 puts "Fiber say bye" end } # 不會立即執行 >> f.resume # 輸出 Fiber say hi >> f.resume # 輸出 Fiber say bye # 輸出 Fiber say hi >> f.resume # 輸出 Fiber say bye >> f.resume FiberError: dead fiber called from (irb):78:in `resume' from (irb):78 from /usr/local/bin/irb19:12:in `<main>'
2009年4月19日星期日
Fibers 用途 • 實做 Enumerator 外部迭代子 • 擴充 fiber library 可以將控制權轉給別的 fiber object
continuation 機制 • 取代難以實做的 (Ruby 1.8 的 continuation 從 kernel 移到 library)
•
日常生活應該用不到... zzz
2009年4月19日星期日
Native Threads threads • Green 所有 Ruby thread 共用一個 native thread
1.8
(operation system) thread • Native 每個 Ruby thread 配一個 native thread
1.9
2009年4月19日星期日
GIL
Giant Interpreter Lock
• 由於部份 C extension libraries 並不
1.9
thread safe,所以實作上同一時間只會有 一個 Thread 在執行。 (據說將來會解鎖,所以目前最好的 Ruby Threads 實做應該是 JRuby)
2009年4月19日星期日
4. Ruby on Rails
2009年4月19日星期日
Ruby 1.9 on Rails • Rails 2.3.2 or edge • mysql-ruby driver for Ruby 1.9 • Passenger(mod_rails) or Thin
2009年4月19日星期日
Upgrade issue 哪裡會爆炸
• program source encoding problem •
invalid multibyte char 如果有中文在原始碼中,一定要加 # encoding: UTF-8
• •
資料庫撈出來的資料被認為是 ACSII-8BIT (binary),無法與 UTF-8 String 相加
•
http://isitruby19.com/
• encoding compatibility problem http://github.com/hectoregm/mysql-ruby (UTF-8 friendly)
• some gem, plugins are not Ruby 1.9 compatible
2009年4月19日星期日
Benchmark 我的實驗
• Rails 2.3.2 production mode • No DB, just render :text => 'hello' • My MacBook Pro 2.2G • httperf
2009年4月19日星期日
Performance Reply rate [replies/s]
Ruby 1.8.6 Mongrel 1.1.5 Ruby 1.8.6 mod_rails Ruby 1.9.1 mod_rails Ruby 1.8.6 Thin 1.0.0 Ruby 1.9.1 Thin 1.0.0 2009年4月19日星期日
min
avg
max
stddev
241.8
258.3
267.4
14.4
244.6
260.9
271.2
11.4
264.0
269.5
273.4
4.9
244.5
273.2
299.6
22.7
348.4
363.2
371.2
12.8
Performance
Ruby 1.9 快兩倍,不表示 Rails Stack 也可以快兩倍!! 400 300
Ruby 1.8.6/Mongrel 1.1.5 Ruby 1.8.6/mod_rails edge Ruby 1.9.1/mod_rails edge Ruby 1.8.6/Thin 1.0.0 Ruby 1.9.1/Thin 1.0.0
200 100 0
2009年4月19日星期日
Reply rate [replies/s]
Performance
Ruby 1.9 快兩倍,不表示 Rails Stack 也可以快兩倍!! 果然天底下沒 這麼好的事
400 300
Ruby 1.8.6/Mongrel 1.1.5 Ruby 1.8.6/mod_rails edge Ruby 1.9.1/mod_rails edge Ruby 1.8.6/Thin 1.0.0 Ruby 1.9.1/Thin 1.0.0
200 100 0
2009年4月19日星期日
Reply rate [replies/s]
5. Conclusion 結論
2009年4月19日星期日
TIOBE Programming Community Index for April 2009
2009年4月19日星期日
Ruby challenge • Ruby 1.9 change a lot and 1.8 is slow and should be deprecated.
• Migrate to Ruby 1.9 is the big challenge in 2009.
2009年4月19日星期日
Reference • •
•
2009年4月19日星期日
Understanding M17n
http://blog.grayproductions.net/articles/understanding_m17n
Books
• • • •
Programming Ruby 1.9 (Pragmatic) The Ruby Programming Language (O’Reilly) Ruby Best Practices (O’Reilly) The Well-Grounded Rubyist (Manning)
Slide
• •
MigrationToRuby 1.9
•
Matz on Ruby 1.9
Ruby 1.9: What to Expect http://slideshow.rubyforge.org/ruby19.html
Other reference links • • • •
http://svn.ruby-lang.org/repos/ruby/tags/v1_9_1_0/NEWS
•
http://dablog.rubypal.com/2009/1/16/son-of-10-things-to-be-aware-of-inruby-1-9
•
http://blog.kineticweb.com/articles/2009/01/30/ruby-1-9-1-the-other-features
2009年4月19日星期日
http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed http://blog.grayproductions.net/articles/getting_code_ready_for_ruby_19 http://dablog.rubypal.com/2009/1/14/10-things-to-be-aware-of-in-moving-toruby-1-9
Thank you.
2009年4月19日星期日
Bonus
2009年4月19日星期日
Object#tap 串接用 puts "dog".reverse .tap{ |o| puts "reversed: #{o}" } .upcase # 輸出 reversed: god GOD
2009年4月19日星期日
回傳原物件