Transcript
Page 1: Migrating to Ruby 1.9

Ruby 1.9Migrating to

Bruce Williams

Page 2: Migrating to Ruby 1.9

Bruce WilliamsRubyist since 2001

Open source developer, contributer, technical editor, designerOccasionally blogs at http://codefluency.com

(Full-time since 2005)

Perpetrator of much random Ruby hackery, language tourist

Page 3: Migrating to Ruby 1.9

Stable.

The syntax and language features you know and probably love.

The performance profile you know and might hate a little.

Unstable, transitional.

Many new syntax and language features.

Better performance, especially for computationally intensive operations.

Ruby 1.9Ruby 1.8

Page 4: Migrating to Ruby 1.9

1.9 is a hint.

Page 5: Migrating to Ruby 1.9

1.9 is a hint.Get ready for 2.0.

Page 6: Migrating to Ruby 1.9

1.8.61.8.51.8.4

1.8.31.8.21.8.1

1.8.01.6.81.6.71.6.21.6.1

1.6.01.5

1.71.9

1.6.41.6.51.6.3

Japan Beyond Japan “... on Rails” Expansion

‘00 ‘01 ‘02 ‘03 ‘04 ‘05 ‘06 ‘07 ‘08

(dev)(dev)

Ruby’s ReleasesFrom Toybox to Toolshed

(dev)

Page 7: Migrating to Ruby 1.9

Standard Library

+rubygems (+ prelude & ruby --disable-gems), rake, json (pure,

ext), ripper, probeprofiler, securerandom, HMAC digests

- soap, wsdl, base64, some rarely used, old libraries

~ csv replaced by FasterCSV implementation

Page 8: Migrating to Ruby 1.9

Parser ChangesFlexibility and Obscurity (for the moment)

Page 9: Migrating to Ruby 1.9

{a: "foo"}# => {:a=>"foo"}

{a: "bar", :b => "baz"}# => {:a=>"bar", :b=>"baz"}

Parser ChangesNew Hash Literal

Page 10: Migrating to Ruby 1.9

Parser ChangesNew Proc Literal

multiply_by_2 = ->(x) { x * 2 }# => #<Proc:0x3c5a50>

multiply_by_2.(4)# => 8

Page 11: Migrating to Ruby 1.9

Parser ChangesSplat more flexibly

names = %w(joe john bill)[*names, 'jack']# => ["joe", "john", "bill", "jack"]

Page 12: Migrating to Ruby 1.9

Parser ChangesMethod parameter ordering

def say(language=:english, text) puts Translator[language].translate(text)endsay "hello"# hellosay :spanish, "hello"# hola

Page 13: Migrating to Ruby 1.9

Text processing

“Clever” assignment with blocks

Some Hash enumerations

Metaprogramming, code generation

Migration Risk Factors

Page 14: Migrating to Ruby 1.9

I was surprised at how much work my 11th hour integration of the FasterCSV code was. It was a pure Ruby library that really didn't do a lot of fancy tricks, but I had to track down about 20 little issues to get it running under Ruby 1.9. Thank goodness it had terrific test coverage to lead me to the problem areas.

- James Edward Gray II

Tests are Good

Follow-up at http://blog.grayproductions.net/articles/getting_code_ready_for_ruby_19

Page 15: Migrating to Ruby 1.9

Block Local VariablesArguments are always local

item = 12.upto(4) do |item| p itemend# Outputs:# 2# 3# 4item# => 4

item = 12.upto(4) do |item| p itemend# Outputs:# 2# 3# 4item# => 1

Ruby 1.9Ruby 1.8

Page 16: Migrating to Ruby 1.9

Shadowing VariablesYou’ll get a warning

Ruby 1.9Ruby 1.8

i = 1lambda { |i| p i }.call(3)# Outputs# 3i# => 3

i = 1lambda { |i| p i }.call(3)# Outputs# 3i# => 1

-e:2: warning: shadowing outer local variable - i

Page 17: Migrating to Ruby 1.9

Shadowing VariablesLocals, but warned

-e:2: warning: shadowing outer local variable - d

d = 2->(;d) { d = 1 }.()d# => 2

d = 2-> { d = 1 }.()d# => 1

(Ruby 1.9)

No local, reassigns Local, shadowed

Page 18: Migrating to Ruby 1.9

Hash#select (etc)Changes to yielded arguments

Ruby 1.9Ruby 1.8conferences.select do |data| p dataend# [:euruko, "Prague"]# [:scotland_on_rails, "Edinburgh"]# [:railsconf_europe, "Berlin"]

conferences.select do |data| p dataend# :euruko# :scotland_on_rails# :railsconf_europe

conferences.select do |name, city| p [name, city]end# [:euruko, "Prague"]# [:scotland_on_rails, "Edinburgh"]# [:railsconf_europe, "Berlin"]

warning: multiple values for a block parameter (2 for 1)

Page 19: Migrating to Ruby 1.9

Hash#select (etc)Returns a Hash

Ruby 1.9Ruby 1.8conferences.select do |name, _| name == :scotland_on_railsend# => [[:scotland_on_rails, "Edinburgh"]]

conferences.select do |name, _| name == :scotland_on_railsend# => {:scotland_on_rails=>"Edinburgh"}

Page 20: Migrating to Ruby 1.9

FeaturesLots of changes,

some big ones

Page 21: Migrating to Ruby 1.9

Multilingualization(m17n)

There is one type of string, and the encoding is mutable

Strings are no longer Enumerable (use #each_char, #each_line, etc)

The encoding is ‘lazy’ and can be set by probing with

String#ascii_only? and String#valid_encoding?. 

Various ways to set default encoding (commandline, magic comments)

String#[] now returns a String, not a Fixnum (use ord)

Page 22: Migrating to Ruby 1.9

[:ASCII_8BIT, :Big5, :BIG5, :CP949, :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, :SHIFT_JIS, :US_ASCII, :UTF_8, :UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE, :Windows_1251, :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, :WINDOWS_1258, :CP1258, :GB1988, :MacCentEuro, :MACCENTEURO, :MacCroatian, :MACCROATIAN, :MacCyrillic, :MACCYRILLIC, :MacGreek, :MACGREEK, :MacIceland, :MACICELAND, :MacRoman, :MACROMAN, :MacRomania, :MACROMANIA, :MacThai, :MACTHAI, :MacTurkish, :MACTURKISH, :MacUkraine, :MACUKRAINE, :CP950, :EucJP, :EUCJP, :EucJP_ms, :EUCJP_MS, :EUC_JP_MS, :CP51932, :EucKR, :EUCKR, :EucTW, :EUCTW, :EUC_CN, :EucCN, :EUCCN, :GB12345, :CP936, :ISO_2022_JP, :ISO2022_JP, :ISO_2022_JP_2, :ISO2022_JP2, :ISO8859_1, :Windows_1252, :WINDOWS_1252, :CP1252, :ISO8859_2, :Windows_1250, :WINDOWS_1250, :CP1250, :ISO8859_3, :ISO8859_4, :ISO8859_5, :ISO8859_6, :Windows_1256, :WINDOWS_1256, :CP1256, :ISO8859_7, :Windows_1253, :WINDOWS_1253, :CP1253, :ISO8859_8, :Windows_1255, :WINDOWS_1255, :CP1255, :ISO8859_9, :Windows_1254, :WINDOWS_1254, :CP1254, :ISO8859_10, :ISO8859_11, :TIS_620, :Windows_874, :WINDOWS_874, :CP874, :ISO8859_13, :Windows_1257, :WINDOWS_1257, :CP1257, :ISO8859_14, :ISO8859_15, :ISO8859_16, :CP878, :SJIS, :Windows_31J, :WINDOWS_31J, :CP932, :CsWindows31J, :CSWINDOWS31J, :MacJapanese, :MACJAPANESE, :MacJapan, :MACJAPAN, :ASCII, :ANSI_X3_4_1968, :UTF_7, :CP65000, :CP65001, :UCS_2BE, :UCS_4BE, :UCS_4LE, :CP1251]

Page 23: Migrating to Ruby 1.9

MultilingualizationRead a file with File.read

File.read("input.txt").encoding# => #<Encoding:UTF-8>

File.read("input.txt", encoding: 'ascii-8bit').encoding# => #<Encoding:ASCII-8BIT>

Page 24: Migrating to Ruby 1.9

MultilingualizationRead a file with File.open

result = File.open("input.txt", "r:euc-jp") do |f| f.readendresult.encoding# => #<Encoding:EUC-JP>result.valid_encoding?# => true

Page 25: Migrating to Ruby 1.9

Regular ExpressionsIntegrated “oniguruma” engine

Same basic API

Much better performance

Support for encodings

Extended Syntax

Look-ahead (?=), (?!), look-behind (?<), (?<!)

Named groups (?<>), backreferences, etc

Page 26: Migrating to Ruby 1.9

Regular ExpressionsNamed Groups

"His name is Joe".match(/name is (?<name>\S+)/)[:name]# => "Joe"

Page 27: Migrating to Ruby 1.9

EnumerableEnumerator built-in, returned from Enumerable methods (and those in Array, Dir, Hash, IO, Range, String or Struct that serve the same purposes). Added Enumerator#with_index

%w(Joe John Jack).map.with_index do |name, offset| "#{name} is #{offset + 1}"end# => ["Joe is #1", "John is #2", "Jack is #3"]

Map with index

Page 28: Migrating to Ruby 1.9

Enumerablereduce (inject)

[1,2,3,4].reduce(:+)# => 10

Page 29: Migrating to Ruby 1.9

Enumerable

take

New Enumerable methods take, group_by, drop, min_by, max_by, count, and others.

array = [1, 2, 3, 4, 5]array.take(3)# => [1, 2, 3]array# => [1, 2, 3, 4, 5]

array = [1, 2, 3, 4, 5]array.drop(3)# => [4, 5]array# => [1, 2, 3, 4, 5]

drop

Page 30: Migrating to Ruby 1.9

Hash ChangesInsertion order preserved

conferences = { euruko: 'Prague', scotland_on_rails: 'Edinburgh'}conferences[:railsconf_europe] = 'Berlin'conferences.each do |name, city| p "#{name} is in #{city}"end# "euruko is in Prague"# "scotland_on_rails is in Edinburgh"# "railsconf_europe is in Berlin"conferences.delete(:scotland_on_rails)conferences[:scotland_on_rails] = 'Edinburgh'conferences.each do |name, city| p "#{name} is in #{city}"end# "euruko is in Prague"# "railsconf_europe is in Berlin"# "scotland_on_rails is in Edinburgh"

Page 31: Migrating to Ruby 1.9

thing = Thing.new.tap do |thing| thing.something = 1 thing.something_else = 2end

ObjectAdded tap

Page 32: Migrating to Ruby 1.9

Lambda ChangesObfuscation, ahoy!

New literal syntax more flexible

Not possible in { | | ... } style literals

m = ->(x, &b) { b.(x * 2) if b }m.(3) do |result| puts resultend# Output# 6

->(a, b=2) { a * b }.(3)# => 6

Passing blocks Default arguments

Page 33: Migrating to Ruby 1.9

Symbol ChangesLess sibling rivalry

Indexing into Comparing with a String

Added to_proc

Added =~, [] like String (to_s less needed), sortable

Object#methods, etc now return an array of symbols

:foo[1]# => "o"

:this === "this"# => true

Page 34: Migrating to Ruby 1.9

Similar to Python’s generators

Owe method naming lineage to Lua

Out of scope of the talk, but very cool

For some examples, see:

http://pragdave.blogs.pragprog.com/pragdave/2007/12/pipelines-using.html (and follow-up)

http://www.davidflanagan.com/blog/2007_08.html (older)

Revactor project (Actors in 1.9 using Fibers + Threads)

InfoQ, others...

Fibers“Semi-coroutines”

Page 35: Migrating to Ruby 1.9

This was really just an introduction.

Bruce Williams [email protected] twitter: wbruce


Top Related