# Welcome

Ruby 1.9: What to Expect

# Ice Breaker Ever use a search engine? # Ice Breaker Ever use a search engine? * Because you are here ** I know you are interested in Ruby

# Ice Breaker Ever use a search engine? * Because you are here ** I know you are interested in Ruby

* My name is Sam Ruby # Ice Breaker Ever use a search engine? * Because you are here ** I know you are interested in Ruby

* My name is Sam Ruby ** Perhaps you have heard of me? # Intro * Agile Web Development with Rails * Apache Software Foundation * Atom / Feed Validator * ECMA .Net CLI (No longer active) * PHP Group (No longer active) * Restful Web Services -- intertwingly.net # Ground Rules # Ground Rules * Everything presented here will be online # Ground Rules * Everything presented here will be online * "most important" stuff first # Ground Rules * Everything presented here will be online * "most important" stuff first * Ask questions! # Ground Rules * Everything presented here will be online * "most important" stuff first * Ask questions! * Presentation contains code # Ground Rules * Everything presented here will be online * "most important" stuff first * Ask questions! * Presentation contains code ** Don't focus on the details # Ground Rules * Everything presented here will be online * "most important" stuff first * Ask questions! * Presentation contains code ** Don't focus on the details ** Focus on social ramifications # Part 0

Overview

# What is ruby? # What is ruby? * MRI # What is ruby? * MRI * Rubinius # What is ruby? * MRI * Rubinius -- rubyspec # What is ruby? * MRI * Rubinius -- rubyspec * JRuby # What is ruby? * MRI * Rubinius -- rubyspec * JRuby * IronRuby # What is ruby? * MRI * Rubinius -- rubyspec * JRuby * IronRuby * Ruby.net # What is ruby? * MRI * Rubinius -- rubyspec * JRuby * IronRuby * Ruby.net * MacRuby # What is ruby? * MRI * Rubinius -- rubyspec * JRuby * IronRuby * Ruby.net * MacRuby * MagLev # What is ruby? * MRI * Rubinius -- rubyspec * JRuby * IronRuby * Ruby.net * MacRuby * MagLev * YARV # Ruby 1.9 Major features # Ruby 1.9 Major features * Performance # Ruby 1.9 Major features * Performance * Threads # Ruby 1.9 Major features * Performance * Threads/Fibers # Ruby 1.9 Major features * Performance * Threads/Fibers * Encoding # Ruby 1.9 Major features * Performance * Threads/Fibers * Encoding/Unicode # Ruby 1.9 Major features * Performance * Threads/Fibers * Encoding/Unicode * gems is (mostly) builtin now # Ruby 1.9 Major features * Performance * Threads/Fibers * Encoding/Unicode * gems is (mostly) builtin now ** No contribs # One Lesson If you can only take away one message from this presentation: # One Lesson If you can only take away one message from this presentation: * if statements do not introduce scope in Ruby. # Replace methods {{{ Bilingual Ruby class Employee if String.method_defined?(:encode) def name ... end else def name ... end end end }}} # Replace implementation {{{ Bilingual Ruby if String.method_defined?(:encode) module Builder ... end else class String ... end end }}} # CI Efforts * Ruby * Bacon * Builder * HTML5lib * Libxml2 * OpenID * REXML * Rake (contrib) * XMPP4R # Part 1

What's changed?

# single character strings irb(main):001:0> ?c => "c" # single character strings irb(main):001:0> ?c => "c" irb(main):001:0> ?c => 99 # string index irb(main):001:0> "cat"[1] => "a" # string index irb(main):001:0> "cat"[1] => "a" irb(main):001:0> "cat"[1] => 97 # {"a","b"} no longer supported irb(main):002:0> {1,2} SyntaxError: (irb):2: syntax error, unexpected ',', expecting tASSOC # {"a","b"} no longer supported irb(main):002:0> {1,2} SyntaxError: (irb):2: syntax error, unexpected ',', expecting tASSOC irb(main):001:0> {1,2} => {1=>2} # {"a","b"} no longer supported irb(main):002:0> {1,2} SyntaxError: (irb):2: syntax error, unexpected ',', expecting tASSOC irb(main):001:0> {1,2} => {1=>2} *Action*: Convert to {1 => 2} # Array.to_s now contains punctuation irb(main):001:0> [1,2,3].to_s => "[1, 2, 3]" # Array.to_s now contains punctuation irb(main):001:0> [1,2,3].to_s => "[1, 2, 3]" irb(main):001:0> [1,2,3].to_s => "123" # Array.to_s now contains punctuation irb(main):001:0> [1,2,3].to_s => "[1, 2, 3]" irb(main):001:0> [1,2,3].to_s => "123" *Action*: use .join instead # Colon no longer valid in when statements irb(main):001:0> case 'a'; when /\w/: puts 'word'; end SyntaxError: (irb):1: syntax error, unexpected ':', expecting keyword_then or ',' or ';' or '\n' # Colon no longer valid in when statements irb(main):001:0> case 'a'; when /\w/: puts 'word'; end SyntaxError: (irb):1: syntax error, unexpected ':', expecting keyword_then or ',' or ';' or '\n' irb(main):001:0> case 'a'; when /\w/: puts 'word'; end word # Colon no longer valid in when statements irb(main):001:0> case 'a'; when /\w/: puts 'word'; end SyntaxError: (irb):1: syntax error, unexpected ':', expecting keyword_then or ',' or ';' or '\n' irb(main):001:0> case 'a'; when /\w/: puts 'word'; end word *Action*: use semicolon, then, or newline # block variables now shadow local variables irb(main):001:0> i=0; [1,2,3].each {|i|}; i => 0 # block variables now shadow local variables irb(main):001:0> i=0; [1,2,3].each {|i|}; i => 0 irb(main):002:0> i=0; for i in [1,2,3]; end; i => 3 # block variables now shadow local variables irb(main):001:0> i=0; [1,2,3].each {|i|}; i => 0 irb(main):002:0> i=0; for i in [1,2,3]; end; i => 3 irb(main):001:0> i=0; [1,2,3].each {|i|}; i => 3 # Hash.index deprecated irb(main):001:0> {1=>2}.index(2) (irb):18: warning: Hash#index is deprecated; use Hash#key => 1 # Hash.index deprecated irb(main):001:0> {1=>2}.index(2) (irb):18: warning: Hash#index is deprecated; use Hash#key => 1 irb(main):002:0> {1=>2}.key(2) => 1 # Hash.index deprecated irb(main):001:0> {1=>2}.index(2) (irb):18: warning: Hash#index is deprecated; use Hash#key => 1 irb(main):002:0> {1=>2}.key(2) => 1 irb(main):001:0> {1=>2}.index(2) => 1 # Hash.index deprecated irb(main):001:0> {1=>2}.index(2) (irb):18: warning: Hash#index is deprecated; use Hash#key => 1 irb(main):002:0> {1=>2}.key(2) => 1 irb(main):001:0> {1=>2}.index(2) => 1 *Action*: use Hash.key # Fixnum.to_sym now gone irb(main):001:0> 5.to_sym NoMethodError: undefined method `to_sym' for 5:Fixnum # Fixnum.to_sym now gone irb(main):001:0> 5.to_sym NoMethodError: undefined method `to_sym' for 5:Fixnum irb(main):001:0> 5.to_sym => nil # Fixnum.to_sym now gone (cont'd) {{{ Ruby 1.9 # Find an argument value by name or index. def [](index) lookup(index.to_sym) end }}} # Fixnum.to_sym now gone (cont'd) {{{ Ruby 1.9 # Find an argument value by name or index. def [](index) lookup(index.to_sym) end }}} http://svn.ruby-lang.org/repos/ruby/trunk/lib/rake.rb # hash keys now unordered irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"} => {:a=>"a", :c=>"c", :b=>"b"} # hash keys now unordered irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"} => {:a=>"a", :c=>"c", :b=>"b"} irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"} => {:a=>"a", :b=>"b", :c=>"c"} # hash keys now unordered irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"} => {:a=>"a", :c=>"c", :b=>"b"} irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"} => {:a=>"a", :b=>"b", :c=>"c"} Order is insertion order # stricter unicode regular expressions irb(main):001:0> /\x80/u SyntaxError: (irb):2: invalid multibyte escape: /\x80/ # stricter unicode regular expressions irb(main):001:0> /\x80/u SyntaxError: (irb):2: invalid multibyte escape: /\x80/ irb(main):001:0> /\x80/u => /\x80/u # tr and Regexp now understand Unicode {{{ Ruby 1.9 unicode(string).tr(CP1252_DIFFERENCES, UNICODE_EQUIVALENT). gsub(INVALID_XML_CHAR, REPLACEMENT_CHAR). gsub(XML_PREDEFINED) {|c| PREDEFINED[c.ord]} }}} # pack and unpack
ruby 1.8.6
def xchr(escape=true)
  n = XChar::CP1252[self] || self
  case n when *XChar::VALID
    XChar::PREDEFINED[n] or 
      (n<128 ? n.chr : (escape ? "&##{n};" : [n].pack('U*')))
  else
    Builder::XChar::REPLACEMENT_CHAR
  end
end
unpack('U*').map {|n| n.xchr(escape)}.join
# BasicObject more brutal than BlankSlate irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f NameError: uninitialized constant C::Math # BasicObject more brutal than BlankSlate irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f NameError: uninitialized constant C::Math irb(main):001:0> require 'blankslate' => true irb(main):002:0> class C < BlankSlate; def f; Math::PI; end; end; C.new.f => 3.14159265358979 # BasicObject more brutal than BlankSlate irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f NameError: uninitialized constant C::Math irb(main):001:0> require 'blankslate' => true irb(main):002:0> class C < BlankSlate; def f; Math::PI; end; end; C.new.f => 3.14159265358979 *Action*: use ::Math::PI # degation changes irb(main):002:0> class C < SimpleDelegator; end => nil irb(main):003:0> C.new('').class => String # degation changes irb(main):002:0> class C < SimpleDelegator; end => nil irb(main):003:0> C.new('').class => String irb(main):002:0> class C < SimpleDelegator; end => nil irb(main):003:0> C.new('').class => C irb(main):004:0> # degation changes irb(main):002:0> class C < SimpleDelegator; end => nil irb(main):003:0> C.new('').class => String irb(main):002:0> class C < SimpleDelegator; end => nil irb(main):003:0> C.new('').class => C irb(main):004:0> Defect 17700 # Use of $KCODE produces warnings irb(main):004:1> $KCODE = 'UTF8' (irb):4: warning: variable $KCODE is no longer effective; ignored => "UTF8" # Use of $KCODE produces warnings irb(main):004:1> $KCODE = 'UTF8' (irb):4: warning: variable $KCODE is no longer effective; ignored => "UTF8" irb(main):001:0> $KCODE = 'UTF8' => "UTF8" # instance_methods now an array of symbols irb(main):001:0> {}.methods.sort.last => :zip # instance_methods now an array of symbols irb(main):001:0> {}.methods.sort.last => :zip irb(main):001:0> {}.methods.sort.last => "zip" # instance_methods now an array of symbols irb(main):001:0> {}.methods.sort.last => :zip irb(main):001:0> {}.methods.sort.last => "zip" *Action*: Replace instance_methods.include? with method_defined? # Source file encoding
basic
 # coding: utf-8
emacs
 # -*- encoding: utf-8 -*-
shebang
 #!/usr/local/rubybook/bin/ruby
 # encoding: utf-8
# Real threading * Race conditions * Implicit Ordering Assumptions * Test code # Implications # Implications * Changes are straightforward # Implications * Changes are straightforward * Cumulative effect is massive # Implications * Changes are straightforward * Cumulative effect is massive * 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 # Implications * Changes are straightforward * Cumulative effect is massive * 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 * Emergence of alternate implementations also a source for inertia # Recommendations # Recommendations Encourage Maintainers of gems to: * Produce versions of gems that work with 1.8.x and 1.9 # Recommendations Encourage Maintainers of gems to: * Produce versions of gems that work with 1.8.x and 1.9 * For long term, move to DVCS like git # Rails dependencies *(compact) actionmailer-2.1.0 * actionpack-2.1.0 * activerecord-2.1.0 * activeresource-2.1.0 * activesupport-2.1.0 * builder-2.1.2 * memcache-client-1.5.0 * rails-2.1.0 * rake-0.8.1 * sources-0.0.1 * text-format-0.6.3 * tmail-1.2.3 * tzinfo-0.3.8 * xml-simple-1.0.11 * html-scanner * db2.rb * mysql.rb # Part 2

What's new?

# alternate syntax for symbol as hash keys {{{ Ruby 1.9 {a: b} }}} # alternate syntax for symbol as hash keys {{{ Ruby 1.9 {a: b} redirect_to action: show }}} # alternate syntax for symbol as hash keys {{{ Ruby 1.9 {a: b} redirect_to action: show }}} {{{ Ruby 1.8.6 {:a => b} redirect_to :action => show }}} # block local variables {{{ Ruby 1.9 [1,2].each {|value; t| t=value*value} }}} # Inject methods {{{ Ruby 1.9 [1,2].inject(:+) }}} # Inject methods {{{ Ruby 1.9 [1,2].inject(:+) }}} {{{ Ruby 1.8.6 [1,2].inject {|a,b| a+b} }}} # To enum {{{ Ruby 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 }}} # No block? Enum! {{{ Ruby 1.9 e = [1,2,3].each }}} # Lambda shorthand {{{ Ruby 1.9 p = -> a,b,c {a+b+c} puts p.[1,2,3] }}} # Lambda shorthand {{{ Ruby 1.9 p = -> a,b,c {a+b+c} puts p.[1,2,3] }}} {{{ Ruby 1.8 p = lambda {|a,b,c| a+b+c} puts p.call(1,2,3) }}} # Complex numbers {{{ Ruby 1.9 Complex(3,4) == 3 + 4.im }}} # Decimal is still not the default irb(main):001:0> 1.2-1.1 => 0.0999999999999999 # Regex "properties" {{{ Ruby 1.9 /\p{Space}/ }}} # Regex "properties" {{{ Ruby 1.9 /\p{Space}/ }}} {{{ Ruby 1.8.6 /[:space:]/ }}} # Splat in middle
Ruby 1.9
def foo(first *middle, last)

(->a, *b, c {p a-c}).(*5.downto(1))
# Fibers {{{ Ruby 1.9 f = Fiber.new do a,b = 0,1 Fiber.yield a Fiber.yield b loop do a,b = b,a+b Fiber.yield b end end 10.times {puts f.resume} }}} # Break values {{{ Ruby 1.9 *match =* while line = gets next if line =~ /^#/ break *line* if line.find('ruby') end }}} # "nested" methods {{{ Ruby 1.9 def toggle def toggle "subsequent times" end "first time" end }}} # Questions * Any questions? # Questions * Thanks for coming! * Thanks for coming! # Questions * Thanks for coming! * Thanks for coming! # Questions