What’s new in Ruby 2.0?
Tikkl Tech Talk
Mar 08, 2014
By Kartik Sahoo
Topics
What’s new in Ruby 1.9

BasicObject: A new Root

Insertion-ordered Hash

Block Params are now Local

Splat in middle of Arguments

Default Parameters

New Proc literal & Named groups

Fiber: Lighter than Threads
Topics continues...
What’s new in Ruby 2.0

Keyword Argument

Module#prepend

Lazy Enumerators

Module#refine

“__dir__”, “to_h” and “%i”

Default UTF-8 Encoding
What’s new in Ruby 1.9
BasicObject: A new root
Parent of all classes.

For creating object hierarchy independent of
Ruby’s object hierarchy
class Car

# body

end
# Ruby 1.8

Car.ancestors

=> [Car, Object, Kernel]
# Ruby 1.9

Car.ancestors

=> [Car, Object, Kernel, BasicObject]
# Ruby 1.9

BasicObject.instance_methods

=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
{Hash}
Elements are kept in the order they were inserted
# Ruby 1.8

{:name => 'Gomez', :age => 34, :gender => 'male'} 

=> {:age=>34, :gender=>"male", :name=>"Gomez"}

# Ruby 1.9

{:name => 'Gomez', :age => 34, :gender => 'male'} 

=> {:name=>"Gomez", :age=>34, :gender=>"male"}

Alternative syntax for Symbol as Hash key
# Ruby 1.9

{name: 'Gomez', age: 34, gender: 'male'} 

=> {:name=>"Gomez", :age=>34, :gender=>"male"}

SHORT
Block Params
Block params are now LOCAL
# Ruby 1.8

foo, bar = 10, 20

!
2.times do |foo|

bar = bar + 1

foo = bar + 2

end

!
foo => 24

bar => 22
# Ruby 1.9

foo, bar = 10, 20

!
2.times do |foo|

bar = bar + 1

foo = bar + 2

end

!
foo => 10

bar => 22
Splat in middle of args..
Splats can now be placed anywhere in method
definition

Adds Flexibility
# Ruby 1.9

def report(name, *marks, age =
22)

[name, marks, age]

end

!
report(‘Mark’, 50, 60, 70, 18)

# Ruby 1.8

def report(name, age, *marks)

[name, marks, age]

end

!
report(‘Mark’, 18, 50, 60, 70)

=> "["Mark", [50, 60, 70], 18]
Default Parameters
Any parameter can have default value not only the
trailing ones.

More flexible
# Ruby 1.9

def tech_talk(about = ‘Ruby 2.0’, by = ‘Kartik’, on)

“A Tech Talk about #{about}, by #{by} on #{on}”

end

!
tech_talk(‘1st Mar, 2014’)

=> “A Tech Talk about Ruby 2.0, by Kartik on 1st Mar, 2014”

!
tech_talk(‘Rails 4’, ‘12th Sept, 2013’)

=> “A Tech Talk about Rails 4, by Kartik on 12th Sept, 2013
New Proc literal (->)
Stored blocks
# Ruby 1.8

greet = lambda do |name|

puts “Hello #{name}!”

end

!
greet.call(‘Everyone’)

=> “Hello Everyone!”
# Ruby 1.9

greet = -> (name) do

puts “Hello #{name}!”

end

!
greet.(‘Everyone’)

=> “Hello Everyone!”
Adds Readability
‘lambda’ has a symbolic representation “->”
Proc continues...
lambdas can now have default arguments
# Ruby 1.9

greet = -> (time=‘Morning’, name) do

puts “Good #{time}, #{name}!”

end

!
greet[‘All’]

=> “Good Morning, All!”

!
greet.yield(‘Evening’, ‘Sir’)

=> “Good Evening, Sir!”
Named group
RegExp groups now have names
# Ruby 1.8

“Good Morning, Everyone!”.match(/, (.*)!/)[1]

=> “Everyone”

!
$1 => “Everyone”

# Ruby 1.9

“Good Morning, Everyone!”.match(/, (?<name>.*)!/)[:name]

=> “Everyone”

!
result = “Good Morning, Everyone!”.match(/, (?<name>.*)!/)

=> #<MatchData ", Everyone!" name:"Everyone">

!
result[:name] or result[1] or $1

=> “Everyone”
Fiber: Lighter than Thread
Light-weight processes: Memory footprint is only
4KB.

Code blocks that can be paused and resumed, like
threads.

Never preempted, scheduled by programmer not
VM.

Fiber#resume to run.
Fiber: Example-1
First call to Fiber#resume takes arguments
fiber = Fiber.new do |arg|

puts “In a Fiber”

Fiber.yield arg + 2 

puts “After first yield”

arg = arg + 2

Fiber.yield arg

puts “After second yield”

arg

end

fiber.resume 10

“In a Fiber”

=> 12

!
fiber.resume 20

“After first yield”

=> 12

!
fiber.resume

“After second yield”

=> 12

!
fiber.resume

=> FiberError: dead fiber
called
Fiber: Example-2
Fiber#resume method takes arbitrary number of args
fiber = Fiber.new do |arg1, arg2|

puts “In a Fiber”

temp = arg1, arg2

Fiber.yield arg1 + 2 

puts “After first yield”

Fiber.yield temp

puts “After second yield”

Fiber.yield

end

fiber.resume 10, 20, 30

“In a Fiber”

=> 12

!
fiber.resume 20

“After first yield”

=> [10, 20]

!
fiber.resume

“After second yield”

=> nil

!
fiber.resume 1, 2, 3

=> [1, 2, 3]
IGNORED
Returns the passed args, if no explicit
value to return.
What’s new in Ruby 2.0
Keyword Arguments
New syntax for defining method parameters

Syntax sugar, helps create simpler APIs

Flexible, easy to read, write & more descriptive
def tech_talk(about: ‘Ruby 2.0’, by: ‘Kartik’, at: ‘RubyConf-14’)

“A Tech Talk about #{about} at #{at}, by #{by}”

end

!
tech_talk at: ‘Tikkl India office”

=> “A Tech Talk about Ruby 2.0 at Tikkl India office, by Kartik

!
tech_talk about: ‘Rails 4.0’, by: ‘Mano’

=> “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano”
… Keyword Arguments
Poor readability

Arguments should be in order from left to right
# Alternative-1

def tech_talk(about = ‘Ruby 2.0’, by = ‘Kartik’, at = ‘RubyConf-14’)

“A Tech Talk about #{about} at #{at}, by #{by}”

end

!
tech_talk ‘Tikkl India office”

=> “A Tech Talk about Tikkl India office at RubyConf-14, by Kartik

!
tech_talk ‘Rails 4.0’, ‘Mano’

=> “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano”
… Keyword Arguments
# Alternative-2

def tech_talk(opts = {})

defaults = { about: ‘Ruby 2.0’, by: ‘Kartik’, at: ‘RubyConf-14’ }

opts = defaults.merge(opts)

“A Tech Talk about #{opts[:about]} at #{opts[:at]}, by #{opts[:by]}”

end

!
tech_talk at: ‘Tikkl India office”

=> “A Tech Talk about Ruby 2.0 at Tikkl India office, by Kartik

!
tech_talk about: ‘Rails 4.0’, by: ‘Mano’

=> “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano”

More coding

Method signature doesn’t say much about its args
Module#prepend
Opposite of Module#include

Inserts module in-front of a class it was prepended to
# Ancestor Chain

class Car

end

!
Car.ancestors

=> [Car, Object, Kernel, BasicObject]
Method call in Ruby traverses its ancestor chain
until finds a match.
Module#prepend ...
# Module#include

module After

end

!
class Car

include After

end

!
Car.ancestors

=> [Car, After, Object,
Kernel, BasicObject]
# Module#prepend

module Before

end

!
class Car

prepend Before

end

!
Car.ancestors

=> [Before, Car, Object,
Kernel, BasicObject]
VS
Lazy Enumerators
Lets us handle an array i.e. either huge or infinite.
Ruby <= 2.0

range = 1..Float::INFINITY

range.collect { |x| x*x }.first(5)

!
Endless loop
Range	 firstcollect ArrayArray
Endless Loop Never Executed
each each
… Lazy Enumerators
The right side of Enumeration chain actually
controls the execution flow.
Ruby 2.0

range = 1..Float::INFINITY

range.lazy.collect { |x| x*x }.first(5)

!
=> [1, 4, 9, 16, 25]
Enumerator::Lazy

!
collect method
ArrayEnumerable#firstRange
my block
each
yields
yields
Module#refine
Ruby classes are open. Redefinition and adding
new functionalities are possible.

Scope of these changes are global.
class String

def length

self.reverse

end

end

!
‘Monkey Patching’.length

=> “gnihctaP yeknoM”
… Module#refine
Refinements: To reduce the impact of monkey
patching on other users.
module StringExtensions

refine String do

def greet

“#{self} says: Hello!”

end

end

end

!
=>#<refinement:String@StringEx
tensions>
class Test

using StringExtensions

!
def say

puts ‘Williams’.greet

end

end

!
Test.new.say

=> “Williams says: Hello!”

!
‘Williams’.greet

=> NoMethodError: undefined
method ‘greet’ for String
Literal Symbol Creation (%i)
Returns array of symbols
%i {what’s new in ruby 2.0}

!
=> [:"what's", :new, :in, :ruby, :"2.0"]
“__dir__” returns the directory name of the file
currently being executed.

File.dirname(__FILE___) usages can be replaced
with __dir__
__dir__
“to_h” method
New convention to retrieve hash representation of
an object.
Student = Struct.new(:name, :age, :class) do

def info

#…

end

end

!
Student.new(‘Gomez’, 34, 2).to_h

=> {:name=>"Gomez", :age=>34, :year=>2}
Default Encoding (UTF-8)
In Ruby 1.9.X, default encoding was US-ASCII (7
bits)

To specify different encoding, magic comments were
used.
!
# encoding: UTF-8

OR

# coding: UTF-8

OR

#blah blah coding: US-ASCII
… Why UTF-8 ?
It’s possible to represent the characters of every
encoding in UTF-8.
!
“Olé!”.encode("UTF-8")
=> “Olé!”
!
“Olé!".encode("US-ASCII")
=> Encoding::UndefinedConversionError
Thank You

What's new in Ruby 2.0

  • 1.
    What’s new inRuby 2.0? Tikkl Tech Talk Mar 08, 2014 By Kartik Sahoo
  • 2.
    Topics What’s new inRuby 1.9 BasicObject: A new Root Insertion-ordered Hash Block Params are now Local Splat in middle of Arguments Default Parameters New Proc literal & Named groups Fiber: Lighter than Threads
  • 3.
    Topics continues... What’s newin Ruby 2.0 Keyword Argument Module#prepend Lazy Enumerators Module#refine “__dir__”, “to_h” and “%i” Default UTF-8 Encoding
  • 4.
  • 5.
    BasicObject: A newroot Parent of all classes. For creating object hierarchy independent of Ruby’s object hierarchy class Car # body end # Ruby 1.8 Car.ancestors => [Car, Object, Kernel] # Ruby 1.9 Car.ancestors => [Car, Object, Kernel, BasicObject] # Ruby 1.9 BasicObject.instance_methods => [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
  • 6.
    {Hash} Elements are keptin the order they were inserted # Ruby 1.8 {:name => 'Gomez', :age => 34, :gender => 'male'} => {:age=>34, :gender=>"male", :name=>"Gomez"} # Ruby 1.9 {:name => 'Gomez', :age => 34, :gender => 'male'} => {:name=>"Gomez", :age=>34, :gender=>"male"} Alternative syntax for Symbol as Hash key # Ruby 1.9 {name: 'Gomez', age: 34, gender: 'male'} => {:name=>"Gomez", :age=>34, :gender=>"male"} SHORT
  • 7.
    Block Params Block paramsare now LOCAL # Ruby 1.8 foo, bar = 10, 20 ! 2.times do |foo| bar = bar + 1 foo = bar + 2 end ! foo => 24 bar => 22 # Ruby 1.9 foo, bar = 10, 20 ! 2.times do |foo| bar = bar + 1 foo = bar + 2 end ! foo => 10 bar => 22
  • 8.
    Splat in middleof args.. Splats can now be placed anywhere in method definition Adds Flexibility # Ruby 1.9 def report(name, *marks, age = 22) [name, marks, age] end ! report(‘Mark’, 50, 60, 70, 18) # Ruby 1.8 def report(name, age, *marks) [name, marks, age] end ! report(‘Mark’, 18, 50, 60, 70) => "["Mark", [50, 60, 70], 18]
  • 9.
    Default Parameters Any parametercan have default value not only the trailing ones. More flexible # Ruby 1.9 def tech_talk(about = ‘Ruby 2.0’, by = ‘Kartik’, on) “A Tech Talk about #{about}, by #{by} on #{on}” end ! tech_talk(‘1st Mar, 2014’) => “A Tech Talk about Ruby 2.0, by Kartik on 1st Mar, 2014” ! tech_talk(‘Rails 4’, ‘12th Sept, 2013’) => “A Tech Talk about Rails 4, by Kartik on 12th Sept, 2013
  • 10.
    New Proc literal(->) Stored blocks # Ruby 1.8 greet = lambda do |name| puts “Hello #{name}!” end ! greet.call(‘Everyone’) => “Hello Everyone!” # Ruby 1.9 greet = -> (name) do puts “Hello #{name}!” end ! greet.(‘Everyone’) => “Hello Everyone!” Adds Readability ‘lambda’ has a symbolic representation “->”
  • 11.
    Proc continues... lambdas cannow have default arguments # Ruby 1.9 greet = -> (time=‘Morning’, name) do puts “Good #{time}, #{name}!” end ! greet[‘All’] => “Good Morning, All!” ! greet.yield(‘Evening’, ‘Sir’) => “Good Evening, Sir!”
  • 12.
    Named group RegExp groupsnow have names # Ruby 1.8 “Good Morning, Everyone!”.match(/, (.*)!/)[1] => “Everyone” ! $1 => “Everyone” # Ruby 1.9 “Good Morning, Everyone!”.match(/, (?<name>.*)!/)[:name] => “Everyone” ! result = “Good Morning, Everyone!”.match(/, (?<name>.*)!/) => #<MatchData ", Everyone!" name:"Everyone"> ! result[:name] or result[1] or $1 => “Everyone”
  • 13.
    Fiber: Lighter thanThread Light-weight processes: Memory footprint is only 4KB. Code blocks that can be paused and resumed, like threads. Never preempted, scheduled by programmer not VM. Fiber#resume to run.
  • 14.
    Fiber: Example-1 First callto Fiber#resume takes arguments fiber = Fiber.new do |arg| puts “In a Fiber” Fiber.yield arg + 2 puts “After first yield” arg = arg + 2 Fiber.yield arg puts “After second yield” arg end fiber.resume 10 “In a Fiber” => 12 ! fiber.resume 20 “After first yield” => 12 ! fiber.resume “After second yield” => 12 ! fiber.resume => FiberError: dead fiber called
  • 15.
    Fiber: Example-2 Fiber#resume methodtakes arbitrary number of args fiber = Fiber.new do |arg1, arg2| puts “In a Fiber” temp = arg1, arg2 Fiber.yield arg1 + 2 puts “After first yield” Fiber.yield temp puts “After second yield” Fiber.yield end fiber.resume 10, 20, 30 “In a Fiber” => 12 ! fiber.resume 20 “After first yield” => [10, 20] ! fiber.resume “After second yield” => nil ! fiber.resume 1, 2, 3 => [1, 2, 3] IGNORED Returns the passed args, if no explicit value to return.
  • 16.
  • 17.
    Keyword Arguments New syntaxfor defining method parameters Syntax sugar, helps create simpler APIs Flexible, easy to read, write & more descriptive def tech_talk(about: ‘Ruby 2.0’, by: ‘Kartik’, at: ‘RubyConf-14’) “A Tech Talk about #{about} at #{at}, by #{by}” end ! tech_talk at: ‘Tikkl India office” => “A Tech Talk about Ruby 2.0 at Tikkl India office, by Kartik ! tech_talk about: ‘Rails 4.0’, by: ‘Mano’ => “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano”
  • 18.
    … Keyword Arguments Poorreadability Arguments should be in order from left to right # Alternative-1 def tech_talk(about = ‘Ruby 2.0’, by = ‘Kartik’, at = ‘RubyConf-14’) “A Tech Talk about #{about} at #{at}, by #{by}” end ! tech_talk ‘Tikkl India office” => “A Tech Talk about Tikkl India office at RubyConf-14, by Kartik ! tech_talk ‘Rails 4.0’, ‘Mano’ => “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano”
  • 19.
    … Keyword Arguments #Alternative-2 def tech_talk(opts = {}) defaults = { about: ‘Ruby 2.0’, by: ‘Kartik’, at: ‘RubyConf-14’ } opts = defaults.merge(opts) “A Tech Talk about #{opts[:about]} at #{opts[:at]}, by #{opts[:by]}” end ! tech_talk at: ‘Tikkl India office” => “A Tech Talk about Ruby 2.0 at Tikkl India office, by Kartik ! tech_talk about: ‘Rails 4.0’, by: ‘Mano’ => “A Tech Talk about Rails 4.0 at RubyConf-14, by Mano” More coding Method signature doesn’t say much about its args
  • 20.
    Module#prepend Opposite of Module#include Insertsmodule in-front of a class it was prepended to # Ancestor Chain class Car end ! Car.ancestors => [Car, Object, Kernel, BasicObject] Method call in Ruby traverses its ancestor chain until finds a match.
  • 21.
    Module#prepend ... # Module#include moduleAfter end ! class Car include After end ! Car.ancestors => [Car, After, Object, Kernel, BasicObject] # Module#prepend module Before end ! class Car prepend Before end ! Car.ancestors => [Before, Car, Object, Kernel, BasicObject] VS
  • 22.
    Lazy Enumerators Lets ushandle an array i.e. either huge or infinite. Ruby <= 2.0 range = 1..Float::INFINITY range.collect { |x| x*x }.first(5) ! Endless loop Range firstcollect ArrayArray Endless Loop Never Executed each each
  • 23.
    … Lazy Enumerators Theright side of Enumeration chain actually controls the execution flow. Ruby 2.0 range = 1..Float::INFINITY range.lazy.collect { |x| x*x }.first(5) ! => [1, 4, 9, 16, 25] Enumerator::Lazy ! collect method ArrayEnumerable#firstRange my block each yields yields
  • 24.
    Module#refine Ruby classes areopen. Redefinition and adding new functionalities are possible. Scope of these changes are global. class String def length self.reverse end end ! ‘Monkey Patching’.length => “gnihctaP yeknoM”
  • 25.
    … Module#refine Refinements: Toreduce the impact of monkey patching on other users. module StringExtensions refine String do def greet “#{self} says: Hello!” end end end ! =>#<refinement:String@StringEx tensions> class Test using StringExtensions ! def say puts ‘Williams’.greet end end ! Test.new.say => “Williams says: Hello!” ! ‘Williams’.greet => NoMethodError: undefined method ‘greet’ for String
  • 26.
    Literal Symbol Creation(%i) Returns array of symbols %i {what’s new in ruby 2.0} ! => [:"what's", :new, :in, :ruby, :"2.0"] “__dir__” returns the directory name of the file currently being executed. File.dirname(__FILE___) usages can be replaced with __dir__ __dir__
  • 27.
    “to_h” method New conventionto retrieve hash representation of an object. Student = Struct.new(:name, :age, :class) do def info #… end end ! Student.new(‘Gomez’, 34, 2).to_h => {:name=>"Gomez", :age=>34, :year=>2}
  • 28.
    Default Encoding (UTF-8) InRuby 1.9.X, default encoding was US-ASCII (7 bits) To specify different encoding, magic comments were used. ! # encoding: UTF-8 OR # coding: UTF-8 OR #blah blah coding: US-ASCII
  • 29.
    … Why UTF-8? It’s possible to represent the characters of every encoding in UTF-8. ! “Olé!”.encode("UTF-8") => “Olé!” ! “Olé!".encode("US-ASCII") => Encoding::UndefinedConversionError
  • 30.