The Nuclear Squid Musings on stuff and other things.

Ruby 1.9 - What's new? What's changed?

This is a short overview of all the changes and additions to Ruby 1.9. It is by no means complete. Comments/additions are more than welcome, and I’ll update this list as I discover new stuff.

Generally useful: Run your Ruby programs with the -w flag, and make sure they produce no warnings.

Other resources, which may or may not be accurate:

Please note that currently I don’t cover anything that falls within the new regexp engine, Oniguruma.

Everything in here has been tested with Ruby 1.9.1 RC1.

Changes in Ruby 1.9 vs. Ruby 1.8.6 (and below)

?c now works differently: Instead of returning the ASCII value of the character, you now get a one-character-string:

>> ?c
=> "c"

Along with that, the index operator for Strings now returns strings instead of the ASCII value as well:

>> "ruby"[1]
=> "u"

Use String#ord to get the character encoding. ord returns the encoding of the first character in the string.

Strings are also no longer enumerable, and no longer support each, which is replaced by the each_line and each_byte methods.

Array#to_s now includes punctuation:

>> [1,2,3].to_s
=> "[1, 2, 3]"

Use Array#join for the old behavior.

The when <statement>: <expressions> syntax no longer works, use a semicolon, then or a newline instead.

Block variables now shadow local variables:

>> i = 0
=> 0
>> [1,2,3].each{|i|}
=> [1, 2, 3]
>> i
=> 0

Block variables now must be local variables, so tricks like [1,2,3].each{|@a|} no longer work.

Hashes (or rather, the keys in them) are now sorted, order is insertion order.

BasicObject is a truly basic object. It doesn’t even include Kernel:

>> BasicObject.ancestors
=> [BasicObject]
>> Object.ancestors
=> [Object, Kernel, BasicObject]

You can still refer to stuff from Kernel though by e.g. prefixing it with :::

# This won't work
class C < BasicObject; def f; Math::PI; end; end; C.new.f
# This will work
class C < BasicObject; def f; ::Math::PI; end; end; C.new.f

$KCODE is deprecated, and doesn’t affect anything anymore.

instance_methods now returns an array of symbols, instead of strings. Instead of instance_methods.include?, use method_defined?.

Ruby 1.9 can now properly read source code files encoded in formats other than ASCII, as long as you declare it:

Basic: # coding: utf-8
Emacs: # -*- encoding: utf-8 -*-
Shebang:

#!/usr/local/bin/ruby
# encoding: utf-8

Ruby 1.9 now uses native threads, instead of green threads. There’s still a GIL in place, though. Threadsafety is probably the one thing that will cause the most breakage when migrating to Ruby 1.9.

Continuations are no longer supported. They may return in a future release though, but don’t count on it.

New stuff in Ruby 1.9

Alternate syntax for Symbol => Object hash notation:

>> {:a => "b"}
=> {:a=>"b"}
>> {a: "b"}
=> {:a=>"b"}

Block local variables:

[1,2,3].each{|value;local| local = value**2}

Symbol#to_proc is now part of the language:

>> (1..10).to_a.inject(:+)
=> 55

Enumerators:

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>
>> enum.each{|i| puts i}
1
2
3
4
=> 1..4
>> enum.next
=> 1
>> enum.next
=> 2

Most methods in the Enumerable module now return an Enumerator when they aren’t supplied with a block:

>> enum = (1..4).each
=> #<Enumerator:0x12627c>

Stabby lambda syntax/shorthand:

>> l = -> a,b,c {a+b+c}
=> #<Proc:0x11e798@(irb):26 (lambda)>
>> l[1,2,3]
=> 6
>> l = lambda{|a,b,c| a+b+c}
=> #<Proc:0x09c6f8@(irb):29 (lambda)>
>> l[1,2,3]
=> 6

Both blocks and stabby lambdas now accept default parameters, splats and blocks:

>> l = lambda{|a,b=1| a + b}
=> #<Proc:0x3dd538@(irb):76 (lambda)>
>> l[1]
=> 2
>> l = ->(a,b=1){a+b}
=> #<Proc:0x3d9938@(irb):78 (lambda)>
>> l[1]
=> 2

New calling syntax for lambdas: In addition to call and [], you can now also use .() or yield:

>> l = ->name{puts "Hello, #{name}"}
=> #<Proc:0x3d0b30@(irb):80 (lambda)>
>> l.call("world")
Hello, world
=> nil
>> l["world"]
Hello, world
=> nil
>> l.("world")
Hello, world
=> nil
>> l.yield "world"
Hello, world
=> nil

Lambdas can now also accept blocks in param lists, but there are some limitations when calling them:

>> l = ->(a, &b){b.call(a)}
=> #<Proc:0x142a6c@(irb):24 (lambda)>
>> l.("world") {|who| "Hello, #{who}!"}
=> "Hello, world!"
>> l["world"] {|who| "Hello, #{who}!"}
SyntaxError: (irb):32: syntax error, unexpected tLBRACE_ARG, expecting $end
l["world"] {|who| "Hello, #{who}!"}
            ^
        from /usr/local/bin/irb19:12:in `<main>'
>> # This still works though:
>> blk = lambda{|who| "Hello, #{who}!"}
=> #<Proc:0x3e4414@(irb):33 (lambda)>
>> l["world", &blk]
=> "Hello, world!"
>> l = lambda{|a, &b| b.call(a)}
=> #<Proc:0x133d00@(irb):27 (lambda)>
>> l.("world") {|who| "Hello, #{who}!"}
=> "Hello, world!"

Splats can now be placed anywhere in a method definition:

>> def foo(a,*b,c); p a,b,c; end
=> nil
>> foo(1,2,3,4,5)
1
[2, 3, 4]
5
=> [1, [2, 3, 4], 5]

Method parameters are now more flexible when it comes to default params:

>> def bar(first="default", second)
>>   puts "First: #{first}, Second: #{second}"
>> end
=> nil
>> bar "test"
First: default, Second: test
=> nil
>> bar "another", "test"
First: another, Second: test
=> nil

Fibers are a lightweight alternative to threads.

Nested methods:

>> def test
>>   def test
>>     "every other time"
>>   end
>>   "first time"
>> end
=> nil
>> test
=> "first time"
>> test
=> "every other time"
>> test
=> "every other time"

New Object#tap method:

>> ary = Array.new.tap do |a|
?>   a << "One"
>>   a << "More"
>>   a << "Thing"
>> end
=> ["One", "More", "Thing"]
>> ary
=> ["One", "More", "Thing"]