Boulder Ruby Group Presentation | Ruby (Programming Language) | Thread (Computing)

Ruby 1.

9
Bruce Williams

New in

Thanks for having me out to Boston.
(especially to Thoughtbot & Tammer for the couch surfing opportunity)

Bruce Williams

arabic io english

lisp

c++ esperanto c spanish lojban

Language Geek
self erlang ocaml

ruby
java awk

perl

haskell python

smalltalk objc eiffel

basque

german

russian

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) 1.7 (dev) 1.5 1.6.1 1.6.3 1.6.5 1.6.0 1.6.2 1.6.4 1.6.7 1.6.8 1.8.1 1.8.0 1.8.4 1.8.2 1.8.3 1.8.5 1.8.6 1.8.7 1.9.1 ... (dev) 1.9 ... 2.0

‘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 not psychic) More bugs (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"[0] # => 114

Ruby 1.9
"ruby"[0] # => “r”

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

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

"ruby".unpack('U*') # => [114, 117, 98, 121]

"‫."ﻛﻠﻤﺎت‬unpack('U*')

# => [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
Ruby 1.8
“clever” assignment

Ruby 1.9
item = 1 2.upto(4) do |item| p item end # Outputs: # 2 Shadowing. # 3 Still a bad idea. # 4 Use a different item name. # => 1

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

Risk: Block Var Scope
Ruby 1.9
not declaring local
d = 2 -> { d = 1 }.() d # => 1 changed the outer variable

Ruby 1.9
declaring local
d = 2 ->(;d) { d = 1 }.() d # => 2 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 arityaware. 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
conferences.select do |name, _| name == :lsrc end # => [[:lsrc, "Austin"]]

Ruby 1.9
conferences.select do |name, _| name == :lsrc end # => {:lsrc=>"Austin"}

Risk: Hash Enumerations
Arity matters with Hash#select.

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

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

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

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)
[1,2,3,4].reduce(:+) # => 10 [1,2,3,4].reduce(&:+) # => 10

Symbol or Symbol#to_proc

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

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

Drop
array = [1, 2, 3, 4, 5] array.drop(3) # => [4, 5] array # => [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
m = ->(x, &b) { b.(x * 2) if b } m.(3) do |result| puts result end # Output # 6

Default arguments
->(a, b=2) { a * b }.(3) # => 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
:foo[1] # => "o"

Comparing with a String
:this === "this" # => 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

Sign up to vote on this title
UsefulNot useful