You are on page 1of 47

New in

Ruby 1.9

Bruce Williams
Thanks for having me
out to Boston.

(especially to Thoughtbot & Tammer


for the couch surfing opportunity)
Bruce Williams
lisp
arabic c++
esperanto lojban
english
io c spanish

Language Geek
self ocaml
ruby perl haskell

erlang python
basque german
smalltalk
objc java russian
eiffel awk
Rubyist
:-) 2001...2005
:-) + $ 2005..2008
Open Source
Developer
RTeX, TuneUp, keyword_search, numerous Rails
plugins
A bunch of URLs
http://codefluency.com
http://github.com/bruce
http://fiveruns.com
http://twitter.com/wbruce
and 1.9?
YARV
1.9 is just like 1.7.
Except completely
different.
Stable
Releases (dev)
(dev)
1.7
1.9
(dev) ... 2.0
1.5 1.6.1 1.6.3 1.6.5 1.8.1 1.8.4
1.6.0 1.6.2 1.6.4 1.6.7 1.6.8 1.8.0 1.8.2 1.8.3 1.8.5 1.8.6 1.8.7 1.9.1
...

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

Japan Beyond Japan “... on Rails” Expansion


1.9.1 will be stable.
Expect it around Christmas.
Many new syntax and
language features.

1.9
Not strictly backwards
compatible to 1.8.
Better performance
characteristics.
More bugs (it’s new!)
Many new syntax and
language features.

1.9
Not strictly backwards
compatible to 1.8.
Better performance
Out of scope.
characteristics.
(I’m
More not
bugspsychic)
(it’s new!)
Installing
1.9.0:

http://www.ruby-lang.org/en/downloads/

From Subversion:
$ svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby1.9
$ cd ruby1.9
$ autoconf
$ ./configure --program-suffix=1.9
$ make && sudo make install
Comparison App
$ git clone git://github.com/bruce/compare-1-9.git
$ cd compare-1-9
$ rake db:migrate
$ ruby script/server (use ruby 1.8!)
Standard Library Changes

rubygems, rake, json, ripper, probeprofiler,


securerandom, HMAC digests

csv replaced by FasterCSV implementation

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


Migration
Risk Factors
1
2
3
<obligatory-testing-related-slide bdd-buzzword-compliant=”0”>

Having good test coverage is


very helpful when migrating
code from 1.8 to 1.9.

</obligatory-testing-related-slide>
Risk: Text Processing
Relying on $KCODE, String#[], or String
internals. Parsers especially at risk.

? New encoding support, String#[] returns chr, not ord

Use new encoding conventions.


Get familiar with String#ord and unpack(‘c*’).
Risk: Text Processing
Ruby 1.8 Ruby 1.9
"ruby"[0] "ruby"[0]
# => 114 # => “r”

"‫["ﻛﻠﻤﺎت‬0]
"‫["ﻛﻠﻤﺎت‬0]
# => 217 # => "‫"ك‬

"ruby".unpack('U*') "‫"ﻛﻠﻤﺎت‬.unpack('U*')
# => [114, 117, 98, 121] # => [1603, 1604, 1605, 1575, 1578]
Risk: Block Var Scope
Modifying variables outside the scope of a
block with a block argument. “Clever”
block tricks.

Block variables are always local, and you get


? warnings when shadowing outer local variables

Modify the outer variable manually from inside


the block if needed. Stop being “clever.”
Risk: Block Var Scope
“clever”
Ruby 1.8 assignment Ruby 1.9
item = 1 item = 1
2.upto(4) do |item| 2.upto(4) do |item|
p item p item
end end
# Outputs: # Outputs:
# 2 # 2
Shadowing.
# 3 # 3
# 4 # 4 Still a bad idea.
item item Use a different
# => 4 # => 1 name.
Risk: Block Var Scope
Ruby 1.9 Ruby 1.9
not declaring local declaring local

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

changed the outer variable this didn’t, but you still


get the shadowing warning.
Risk: Hash#select
Expecting an Array result from
Hash#select, or capturing both key and
value in a single block argument.

Hash#select now returns a ... Hash, and it’s arity-


? aware.

Check your loops on results from Hash#select.


You may be able to remove some Hash
re-creation code.
Risk: Hash Enumerations
Hash#select returns a Hash. Yes!

Ruby 1.8 Ruby 1.9


conferences.select do |name, _| conferences.select do |name, _|
name == :lsrc name == :lsrc
end end
# => [[:lsrc, "Austin"]] # => {:lsrc=>"Austin"}
Risk: Hash Enumerations
Arity matters with Hash#select.

Ruby 1.8 Ruby 1.9


conferences.select do |data| conferences.select do |data|
p data p data
end end
# [:lsrc, "Austin"] # :lsrc
# [:scotland_on_rails, "Edinburgh"] # :scotland_on_rails
# [:railsconf_europe, "Berlin"] # :railsconf_europe

conferences.select do |name, city|


warning: multiple values for a block
p [name, city]
parameter (2 for 1) end
# [:lsrc, "Austin"]
# [:scotland_on_rails, "Edinburgh"]
# [:railsconf_europe, "Berlin"]
Risk: Gems
The biggest obstacle to Ruby 1.9’s adoption is
the sheer number of mostly working but
essentially unmaintained gems that virtually
everybody in the Ruby community depends on
- Sam Ruby

Help!
New Features

XL
Multilingualization
(m17n)

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

Strings don’t have #each (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)

# encoding: utf-8

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


[: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, :IS
O_8859_8, :ISO_8859_9, :ISO_8859_10, :ISO_8859_11, :ISO_8859_13, :ISO_8859_14, :IS
O_8859_15, :ISO_8859_16, :KOI8_R, :KOI8_U, :Shift_JIS, :SHIFT_JIS, :US_ASCII, :UTF_8, :UT
F_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE, :Windows_1251, :WINDOWS_1251, :BINARY, :I
BM437, :CP437, :IBM737, :CP737, :IBM775, :CP775, :CP850, :IBM850, :IBM852, :CP852, :IB
M855, :CP855, :IBM857, :CP857, :IBM860, :CP860, :IBM861, :CP861, :IBM862, :CP862, :IBM
863, :CP863, :IBM864, :CP864, :IBM865, :CP865, :IBM866, :CP866, :IBM869, :CP869, :Windo
ws_1258, :WINDOWS_1258, :CP1258, :GB1988, :MacCentEuro, :MACCENTEURO, :MacCroa
tian, :MACCROATIAN, :MacCyrillic, :MACCYRILLIC, :MacGreek, :MACGREEK, :MacIceland, :MAC
ICELAND, :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, :E
UCCN, :GB12345, :CP936, :ISO_2022_JP, :ISO2022_JP, :ISO_2022_JP_2, :ISO2022_JP2, :ISO8
859_1, :Windows_1252, :WINDOWS_1252, :CP1252, :ISO8859_2, :Windows_1250, :WIND
OWS_1250, :CP1250, :ISO8859_3, :ISO8859_4, :ISO8859_5, :ISO8859_6, :Windows_1256,
:WINDOWS_1256, :CP1256, :ISO8859_7, :Windows_1253, :WINDOWS_1253, :CP1253, :IS
O8859_8, :Windows_1255, :WINDOWS_1255, :CP1255, :ISO8859_9, :Windows_1254, :WI
NDOWS_1254, :CP1254, :ISO8859_10, :ISO8859_11, :TIS_620, :Windows_874, :WINDOW
S_874, :CP874, :ISO8859_13, :Windows_1257, :WINDOWS_1257, :CP1257, :ISO8859_14, :
ISO8859_15, :ISO8859_16, :CP878, :SJIS, :Windows_31J, :WINDOWS_31J, :CP932, :CsWindo
ws31J, :CSWINDOWS31J, :MacJapanese, :MACJAPANESE, :MacJapan, :MACJAPAN, :ASCII, :AN
SI_X3_4_1968, :UTF_7, :CP65000, :CP65001, :UCS_2BE, :UCS_4BE, :UCS_4LE, :CP1251]
Regular Expressions
鬼車 Integrated the “Oniguruma” engine

Same basic API


Much better performance
Support for encodings
Extended Syntax
Look-ahead (?=), (?!), look-behind (?<), (?<!)
Named groups (?<>), backreferences, etc

Named Groups
"His name is Joe".match(/name is (?<name>\S+)/)[:name]
# => "Joe"
Multilingualization
Read a file with File.read
File.read("input.txt").encoding
# => #<Encoding:UTF-8>

File.read("input.txt", encoding: 'ascii-8bit').encoding


# => #<Encoding:ASCII-8BIT>

Read a file with File.open


result = File.open("input.txt", "r:euc-jp") do |f|
f.read
end
result.encoding
# => #<Encoding:EUC-JP>
result.valid_encoding?
# => true
Enumerable
Enumerator 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

Map 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"]
Enumerable

Reduce (inject) Symbol


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

[1,2,3,4].reduce(&:+)
# => 10
Enumerable
New Enumerable methods take, group_by, drop, min_by, max_by,
count, and others.

Take Drop
array = [1, 2, 3, 4, 5] array = [1, 2, 3, 4, 5]
array.take(3) array.drop(3)
# => [1, 2, 3] # => [4, 5]
array array
# => [1, 2, 3, 4, 5] # => [1, 2, 3, 4, 5]
Hash Changes
Insertion Order
conferences = {
lsrc: 'Austin',
scotland_on_rails: 'Edinburgh'
}
conferences[:rubyconf] = 'Orlando'
conferences.each do |name, city|
p "#{name} is in #{city}"
end
# "lsrc is in Austin"
# "scotland_on_rails is in Edinburgh"
# "rubyconf is in Orlando"
conferences.delete(:scotland_on_rails)
conferences[:scotland_on_rails] = 'Edinburgh'
conferences.each do |name, city|
p "#{name} is in #{city}"
end
# "lsrc is in Austin"
# "rubyconf is in Orlando"
# "scotland_on_rails is in Edinburgh"
Object

Tap
thing = Thing.new.tap do |thing|
thing.something = 1
thing.something_else = 2
end
New Hash Literal
Symbol shortcut
{foo: 1, bar: 2}
# => {:foo=>1, :bar=>2}

You can mix forms


{foo: 1, 'bar' => 2, 'foo' => 3}
# => {:foo=>1, "bar"=>2, "foo"=>3}

And leave it `open’


some_method "argument1", a: 1, b: 2
New Proc Literal
More flexible

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

Passing blocks Default arguments


m = ->(x, &b) { b.(x * 2) if b } ->(a, b=2) { a * b }.(3)
m.(3) do |result|
# => 6
puts result
end
# Output
# 6
Can be Ugly as Hell
-> a = 1, b = 2, c, &d ; e { e = d.(a * b * c); e + 1 }.(3) { |p| p * 4 }
# => 25

! Don’t do this. Ruby isn’t Perl.


Symbol Changes
Added to_proc

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

Object#methods, etc now return an array of symbols

Indexing into Comparing with a String


:foo[1] :this === "this"
# => "o" # => true
Threads
Moved to a native threading model.

From thread.c (“model 2”):


A thread has mutex (GVL: Global VM Lock) can run. When thread
scheduling, running thread release GVL. If running thread try blocking
operation, this thread must release GVL and another thread can
continue this flow. After blocking operation, thread must check
interrupt (RUBY_VM_CHECK_INTS).

Every VM can run parallel.

Ruby threads are scheduled by OS thread scheduler.


Fibers
“Semi-coroutines.” Think of them as lightweight user threads with
manual scheduling.

Revactor
NeverBlock
http://pragdave.blogs.pragprog.com/pragdave/2007/12/pipelines-using.html
http://www.davidflanagan.com/blog/2007_08.html
InfoQ, others...
Questions?
Thank You.
bruce@codefluency.com
http://twitter.com/wbruce

You might also like