1. Ruby 2
some new things
David A. Black
Lead Developer
Cyrus Innovation
@david_a_black
Ruby Blind meetup
April 10, 2013
2. About me
• Rubyist since 2000 (Pickaxe baby)
• Lead Developer, Cyrus Innovation
• Developer, author, trainer, speaker, event
organizer
• Author of The Well-Grounded Rubyist
• Co-founder of Ruby Central
• Chief author of scanf.rb (standard library)
3. Today's topics
• Lazy enumerators
• Module#prepend
• String#bytes and friends
• Keyword arguments
• Miscellaneous changes and new features
4. Lazy enumerators
What's wrong with this code?
# find the first 10 multiples of 3
(0..Float::INFINITY).select {|x| x % 3 == 0 }.first(10)
5. Lazy enumerators
# find the first 10 multiples of 3
(0..Float::INFINITY).select {|x| x % 3 == 0 }.first(10)
It runs forever!
6. Lazy enumerators
# find the first 10 multiples of 3
(0..Float::INFINITY).lazy.select {|x| x % 3 == 0 }.first(10)
7. Lazy enumerators
# find the first 10 multiples of 3
(0..Float::INFINITY).lazy.select {|x| x % 3 == 0 }.first(10)
=> [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
8. Lazy enumerators
r = 0..Float::INFINITY
s = 0..Float::INFINITY
r.zip(s).first(5) # runs forever
10. Lazy enumerators
# From Ruby source documentation
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
fib.zip(0..Float::INFINITY).first(5) # runs forever
11. Lazy enumerators
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end.lazy
fib.zip(0..Float::INFINITY).first(5)
# => [[1, 0], [1, 1], [2, 2], [3, 3], [5, 4]]
12. Lazy enumerators
• can be created via #lazy on an Enumerable
• [1,2,3].lazy
• (0..Float::INFINITY).lazy
• an_enumerator.lazy (see Fibonacci
example)
13. Module#prepend
What will the output be?
class Person
def talk
puts "Hello"
end
end
module Yeller
def talk
super
puts "I said... HELLLLLOOO!!!!"
end
end
class Person
include Yeller
end
david = Person.new
david.talk
14. Module#prepend
class Person
def talk
puts "Hello"
end
end
module Yeller
def talk
super
puts "I said... HELLLLLOOO!!!!"
end
end
class Person
include Yeller
end
david = Person.new
david.talk
# => Hello
16. Module#prepend
What will the output be?
class Person
def talk
puts "Hello"
end
end
module Yeller
def talk
super
puts "I said... HELLLLLOOO!!!!"
end
end
class Person
prepend Yeller
end
david = Person.new
david.talk
17. Module#prepend
class Person
def talk
puts "Hello"
end
end
module Yeller
def talk
super
puts "I said... HELLLLLOOO!!!!"
end
end
class Person
prepend Yeller
end
david = Person.new
david.talk
# => Hello
I said... HELLLLLOOO!!!!
19. Module#prepend
• Puts the module *before* the receiver
(class or module) in the method lookup
path
• A good way to avoid messing with alias
class Person
def talk
puts "Hello!"
end
end
class Person
alias old_talk talk
def talk
old_talk
puts "I said... HELLLLLOOO!!!!"
end
end
20. String#bytes/each_byte
(and friends)
• String#bytes, #lines, #chars, #codepoints
now return arrays
• #each_byte/line/char/codepoint still return
enumerators
• Saves you having to do #to_a when you
want an array
21. Keyword arguments
def my_method(a, b, c: 3)
p a, b, c
end
my_method(1, 2) # 1 2 3
my_method(1, 2, c: 4) # 1 2 4
Lets you specify a default value for a
parameter, and use the parameter's name in
your method call
22. Keyword arguments
def my_method(a, b, *array, c: 3)
p a, b, array, c
end
my_method(1, 2, 3, 4, c: 5) # 1, 2, [3, 4], 5
Non-keyword arguments still work
essentially the same way that they did.
23. Keyword arguments
def my_method(a, b, *array, c: 3, **others)
p a, b, array, c, others
end
my_method(1, 2, 3, 4, c: 5, d: 6, e: 7)
# 1, 2, [3, 4], 5, {:d=>6, :e=>7}
Extra keyword arguments get passed
along in the **others parameter.
24. Keyword arguments
def my_method(a, b, c)
p a, b, c
end
my_method(1, 2, z: 3) # 1 2 {:z=>3}
Hash-like arguments that don't
correspond to a named argument get
passed along as a hash.
25. Keyword arguments
Order doesn't matter:
class Person
attr_accessor :name, :email, :age
def initialize(name: "", email: "", age: 0)
self.name = name
self.email = email
self.age = age
end
end
david = Person.new(email: "dblack@rubypal.com",
name: "David",
age: Float::INFINITY)
26. Miscellaneous
• %i{} and %I{}
• Default encoding now UTF-8 (no need for magic
comment)
• Struct#to_h, nil#to_h, Hash#to_h
• Kernel#Hash (like Array, Integer, Float)
• const_get now parses nested constants
• Object.const_get("A::B::C")
• #inspect doesn't call #to_s any more
27. • Questions?
• Comments?
David A. Black
Lead Developer
Cyrus Innovation
@david_a_black
Ruby Blind meetup
April 10, 2013