Ruby 1.8とRuby 1.9の変更点の生成を半自動化

http://eigenclass.org/hiki/mechanically-verified-ruby19-changelog

クリスマスリリースされるであろうRuby 1.9はかなり久々の大きなバージョンアップだ。Ruby 1.8時代がかつてないほどに長かった。これからは1.8、1.9が共存していく。安定を望む人はこれまで通り1.8を使えばいいし、よりパワーアップしたRubyを使いたければ1.9を使えばいい。
Ruby 1.9では新しい文法やいろいろな非互換性がある。進化する上で非互換性は仕方ない。変更点がどうなったのか気になっている人は多いだろう。eigenclass.orgの中の人は今まで時間をかけて変更点のチェックしていた。しかし、1.9開発中にはいろいろな機能ができては消えてきた。だから手作業でチェックしていたら内容の信憑性が怪しい。そこで、彼は変更点を自動生成することにした。比較コード、ドキュメント、動作検証用コード(assertion)をひとつのRubyスクリプトに詰め込んだ。そのRubyスクリプトを実行することで変更点が半自動的に生成されるというわけだ。比較コードはxmpfilterによりRuby 1.8Ruby 1.9の双方で結果が出てくる。もし、assertionがコケたら、「Invalid change descriptions(変更点ドキュメントの誤り)」として出力されるから、ドキュメントを修正すればいい。ナイスアイデア!かっこいいなぁ…

さて、検証するにはdarcsでリポジトリを得る必要がある。ruby18-19.rbの引数にはRuby 1.8Ruby 1.9の実行ファイル名を指定する。

ちなみに、ruby-changelogソースコードはおもしろいDSLになっているので、読んでみると勉強になる。

追記

リリース版に変更してみた。

$ cd ~/src
$ darcs get http://eigenclass.org/repos/ruby-changelog
$ cd ruby-changelog
$ ruby ruby18-19.rb ruby18 ruby19
About this document
-------------------
This document was generated semi-automatically by a Ruby program
that annotates the code snippets and checks the assertions attached
to the descriptions.

The annotations are generated by xmpfilter (see
http://eigenclass.org/hiki/rcodetools). This is the notation used
in the snippets below:
  expr          # => the value expr evaluates to
  whatever      # !> a warning issued by ruby
  puts "stuff output to stdout"
  # >> stuff output to stdout

These are the versions of the interpreters used to evaluate the
examples:

ruby 1.9.0:
  RUBY_VERSION                                   # => "1.9.0"
  RUBY_PATCHLEVEL                                # => 0
  RUBY_RELEASE_DATE                              # => "2007-12-25"

ruby 1.8.6:
  RUBY_VERSION                                   # => "1.8.6"
  RUBY_PATCHLEVEL                                # => 111
  RUBY_RELEASE_DATE                              # => "2007-09-24"

Syntax
======

New hash literal
----------------
ruby 1.9.0:
  { a: "foo" }                                # => {:a=>"foo"}

Block local variables
---------------------
You can declare block local variables with this syntax: 
  {|normal args; local variables| ...}
When a variable is shadowed, ruby1.9 issues a warning.

ruby 1.9.0:
  d = 2
  a = lambda{|;d| d = 1} # !> shadowing outer local variable - d
  a.call()
  p d
  # >> 2

Block arguments are always local
--------------------------------
ruby 1.9.0:
  a = 1
  10.times{|a| } # !> shadowing outer local variable - a
  p a
  # >> 1

ruby 1.8.6:
  a = 1
  10.times{|a| }
  p a
  # >> 9

New syntax for lambdas (VERY EXPERIMENTAL)
------------------------------------------
Note that this does not replace the traditional block syntax. Matz
has already said the latter is here to stay, forever.  The new
syntax allows to specify default values for block arguments, since
{|a,b=1| ... } is said to be impossible with Ruby's current LALR(1)
parser, built with bison.

You can use the new syntax without parenthesis for the arguments.

ruby 1.9.0:
  a = ->(b,c){ b + c }
  a.call(1,2) # => 3
---
  -> { }.call # => nil
  -> a, b  { a + b }.call(1,2) # => 3
  c = 1; -> a, b; c  { c = a + b }.call(1,2); c # => 1 # !> shadowing outer local variable - c
---
  # things get tricky...
  c = 2; -> ;c { c = 1 }.call; c # => 2 # !> shadowing outer local variable - c
---
  # or even...
  c = 2; -> *d ; c { d }.call(1,2,3) # => [1, 2, 3] # !> shadowing outer local variable - c
  c = 2; -> ; c { c = 1 }.call; c    # => 2 # !> shadowing outer local variable - c

.() and calling procs without call/[] (EXPERIMENTAL)
----------------------------------------------------
You can call a proc with .() (the period is needed).

ruby 1.9.0:
  a = lambda{|*b| b}
  a.(1,2)                # => [1, 2]
---
  a = lambda{|*b| b}
  a(1,2)                # => 
  # ~> -:2:in `<main>': undefined method `a' for main:Object (NoMethodError)

Block arguments passed to blocks
--------------------------------
Blocks can take &block arguments ([[ruby-dev:23533]]).

ruby 1.9.0:
 /tmp/ruby-changelog.20784.21:2: warning: multiple values for a block parameter (2 for 1)
	from /tmp/ruby-changelog.20784.21:1
 define_method(:foo){|&b| b.call(bar)}
  # ~> -:1:in `<main>': undefined method `define_method' for main:Object (NoMethodError)

Block argument assignment
-------------------------
|v| now works like the former |v,|:

ruby 1.9.0:
  def m; yield 1, 2; end
  p m{|v| v}
  # >> 1

ruby 1.8.6:
  def m; yield 1, 2; end
  p m{|v| v} # !> multiple values for a block parameter (2 for 1)
  # >> [1, 2]

Multiple splats allowed
-----------------------
As suggested by Audrey Tang, 1.9 allows multiple splat operators when calling
a method. Multiple splats are also allowed in array expressions.

ruby 1.9.0:
  def foo(*a)
    a
  end
   
  p foo(1, *[2,3], 4, *[5,6])
  # >> [1, 2, 3, 4, 5, 6]
---
  a = [1,2,3]
  b = [4,5,6]
  p [*a, *b]
  # >> [1, 2, 3, 4, 5, 6]

Mandatory arguments after optional ones allowed
-----------------------------------------------
See [[ruby-dev:29014]].

ruby 1.9.0:
  def m(a, b=nil, *c, d)
    [a,b,c,d]
  end
  p m(1,2)
  # >> [1, nil, [], 2]

?c semantics
------------
?a now returns a single character string instead of an integer.

ruby 1.9.0:
  ?a                                           # => "a"

ruby 1.8.6:
  ?a                                           # => 97

Arguments to []
---------------
You can use splats and "assocs" (hashes without braces) with [].

ruby 1.9.0:
  class Foo; def [](*a); a end end
  a = (0..3).to_a
  p Foo.new[*a, :op => :+]
  # >> [0, 1, 2, 3, {:op=>:+}]

Newlines before the ternary color
---------------------------------
See [[ruby-dev:29189]].

ruby 1.9.0:
  p 1 == 2 ?
    0
    :
    1
  # >> 1

defined? and local variables
----------------------------
ruby 1.9.0:
  a = 0
  defined? a                                        # => "local-variable"
  1.times do |i|
    defined? i                                      # => "local-variable"
  end

ruby 1.8.6:
  a = 0
  defined? a                                        # => "local-variable"
  1.times do |i|
    defined? i                                      # => "local-variable(in-block)"
  end

Kernel and object
=================

BasicObject
-----------
BasicObject is a top level "BlankSlate" class.

ruby 1.9.0:
  BasicObject.instance_methods                 # => [:==, :equal?, :"!", :"!=", :__send__]
  Object.ancestors                             # => [Object, Kernel, BasicObject]

Kernel#instance_exec
--------------------
Allows to evaluate a block with a given ''self'', while passing arguments

ruby 1.9.0:
  def magic(obj); def obj.foo(&block); instance_exec(self, a, b, &block) end end
  o = Struct.new(:a,:b).new(1,2)
  magic(o)
  o.foo{|myself,x,y| x + y }                # => 3

Kernel#public_send
------------------
public_send only calls public methods. You can call private methods
(as usual) using send.

ruby 1.9.0:
  class Foo; private; def foo; end; end
  Foo.new.send(:foo)                # => nil
  Foo.new.public_send(:foo)
  # ~> -:3:in `public_send': private method `foo' called for #<Foo:0xb7b831e0> (NoMethodError)
  # ~> 	from -:3:in `<main>'
---
  class Klass
    def hello(*args)
      "Hello " + args.join(' ')
    end
  end
  k = Klass.new
  k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
  
  send(:puts, "foo")    # prints "foo"
  1.public_send(:puts, "foo")  # NoMethodError exception
  # ~> -:10:in `public_send': private method `puts' called for 1:Fixnum (NoMethodError)
  # ~> 	from -:10:in `<main>'
  # >> foo

Kernel#require
--------------
The value stored in ''$"'' when requiring a file contains the full path, i.e.
it works like
 $" << File.expand_path(loaded_file)
[[ruby-dev:26079]]

Object#=~
---------
Now returns nil instead of false. [[ruby-core:05391]]

ruby 1.9.0:
  1 =~ 1                                       # => nil

Object#tap
----------
Passes the object to the block and returns it (meant to be used for call
chaining).

ruby 1.9.0:
  "F".tap{|x| x.upcase!}[0]                       # => "F"
  # Note that "F".upcase![0] would fail since upcase! would return nil in this
  # case.

Kernel#instance_variable_defined?
---------------------------------
ruby 1.9.0:
  a = "foo"
  a.instance_variable_defined? :@a                  # => false
  a.instance_variable_set(:@a, 1)
  p a.instance_variable_defined?(:@a) 
  # >> true

define_singleton_method
-----------------------
ruby 1.9.0:
  a = ""
  a.define_singleton_method(:foo){|x| x + 1}
  a.send(:foo, 2)                                           # => 3
  
  # the method is private
  a = ""
  a.define_singleton_method(:foo){|x| x + 1}
  a.foo(2)

Kernel#singleton_methods, methods
---------------------------------
They now return an array of symbols (instead of strings).

ruby 1.9.0:
  a = ""
  class << a; def foo; end end
  p a.singleton_methods                               # => [:foo]
  # >> [:foo]

Class and Module
================

Module#instance_methods, #private_instance_methods, #public_instance_methods
----------------------------------------------------------------------------
They now return an array of symbols (instead of strings).

ruby 1.9.0:
  class X; def foo; end end
  p X.instance_methods(false)
  # >> [:foo]

ruby 1.8.6:
  class X; def foo; end end
  p X.instance_methods(false)
  # >> ["foo"]

Module#const_defined?, #const_get and #method_defined?
------------------------------------------------------

      These methods now accept a flag specifying whether ancestors will be
      included in the chain, which defaults to true. See [[ruby-talk:175899]].

ruby 1.9.0:
  module A; X = 1; def foo; end end
  module B 
    include A
    const_defined? "X"                              # => true
    method_defined? :foo                            # => true
    method_defined? :foo, false                     # => 
    const_get "X"                                   # => 
  end
  # ~> -:6:in `method_defined?': wrong number of arguments(2 for 1) (ArgumentError)
  # ~> 	from -:6:in `<module:B>'
  # ~> 	from -:2:in `<main>'

ruby 1.8.6:
  module A; X = 1; def foo; end end
  module B 
    include A
    const_defined? "X"                              # => false
    method_defined? :foo                            # => true
    const_get "X"             /tmp/ruby-changelog.20784.9:4: warning: parenthesize argument(s) for future version
                      # => 1
  end

Module#class_variable_set, get
------------------------------
They are public in 1.9, private in 1.8:

ruby 1.9.0:
  class B; self end.class_variable_set(:@@a, "foo")                # => "foo"

ruby 1.8.6:
  class B; self end.class_variable_set(:@@a, "foo")                # => 
  # ~> -:1: private method `class_variable_set' called for B:Class (NoMethodError)

Module#attr
-----------
Use 
 attr :foo=
to create a read/write accessor.  (RCR#331)

Class of singleton classes
--------------------------
Singleton classes inherits from Class rather than from the
class of its object. See [[ruby-dev:23690]].

ruby 1.9.0:
  class X; end
  x = X.new
  class << x; p(self < X); end
  # >> true

ruby 1.8.6:
  class X; end
  x = X.new
  class << x; p(self < X); end
  # >> nil

Module#module_exec
------------------
Similar to Object#instance_exec.

Extra subclassing check when binding UnboundMethods
---------------------------------------------------
The check is performed at definition ti/tmp/ruby-changelog.20784.19:2: private method `eval' called for #<Binding:0xb7dfaab8> (NoMethodError)
me, not when the method is
executed. See [[ruby-dev:23410]].

ruby 1.9.0:
  class Foo; def foo; "Foo#foo" end end
  module Bar 
    define_method(:foo, Foo.instance_method(:foo))
  end
  a = "1"
  a.extend Bar
  a.foo                                        # => 
  # ~> -:3:in `define_method': bind argument must be a subclass of Foo (TypeError)
  # ~> 	from -:3:in `<module:Bar>'
  # ~> 	from -:2:in `<main>'

ruby 1.8.6:
  class Foo; def foo; "Foo#foo" end end
  module Bar 
    define_method(:foo, Foo.instance_method(:foo))
  end
  a = "1"
  a.extend Bar
  a.foo                                        # => 
  # ~> -:7:in `foo': bind argument must be an instance of Foo (TypeError)
  # ~> 	from -:7

Binding#eval
------------
RCR 251

ruby 1.9.0:
  a = 1
  p binding.eval("a")
  # >> 1

ruby 1.8.6:
  a = 1
  p binding.eval("a")
  # ~> -:2: private method `eval' called for #<Binding:0xb7e13acc> (NoMethodError)

Blocks and Procs
================

Proc#yield
----------
Invokes the block, setting the block's parameters /tmp/ruby-changelog.20784.28:4: syntax error, unexpected tLBRACE_ARG, expecting $end
      s[/d/]{|x| digits << x; sum += x.to_i } 
             ^
to the values in
params in the same manner the yield statement does.
NilClass#yield raises a LocalJumpError so you can use it on &block.

ruby 1.9.0:
  a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
  a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]
  a_proc.yield([9, 1, 2, 3]) #=> [9, 18, 27]
  a_proc = Proc.new {|a,b| a}
  p a_proc.yield(1,2,3)
  # >> 1

Arity of blocks without arguments
---------------------------------
Arity is now defined as number of parameters that would not be ignored.
See [[ruby-talk:120253]] and http://rcrchive.net/rcr/show/227.

ruby 1.9.0:
  lambda{}.arity  # => 0
  lambda{}.call(1)
  # ~> -:2:in `call': wrong number of arguments (1 for 0) (ArgumentError)
  # ~> 	from -:2:in `<main>'

ruby 1.8.6:
  lambda{}.arity  # => -1
  lambda{}.call(1)

proc is now a synonym of Proc.new
---------------------------------
proc is an alias of Proc.new, so it receives its arguments with
multiple-assignment (block) semantics, instead of lambda ones as in 1.8,
where proc and lambda where synonyms.

ruby 1.9.0:
  Proc.new{|a,b|}.arity          # => 2
  Proc.new{|a,b|}.call(1)        # = nil
  proc{|a,b|}.arity              # => 2
  proc{|a,b|}.call(1)            # => nil

ruby 1.8.6:
  Proc.new{|a,b|}.arity          # => 2
  Proc.new{|a,b|}.call(1)        # = nil
  proc{|a,b|}.arity              # => 2
  proc{|a,b|}.call(1)            # => 
  # ~> -:4: wrong number of arguments (1 for 2) (ArgumentError)
  # ~> 	from -:4:in `call'
  # ~> 	from -:4

Proc#lambda?
------------
Returns whether the Proc has got "lambda semantics" or "block
semantics".

Exceptions
==========

Equality of exceptions
----------------------
They are now considered equal if they have the same class, message and
backtrace ([[ruby-talk:110354]]).

ruby 1.9.0:
  def method
    raise 'foobar'
  end
  
  errors = []
  2.times do
    Thread.new do
      begin
        method
      rescue => e
        errors << e
      end
    end.join
  end
  
  errors[-2] == errors[-1]             # => true

ruby 1.8.6:
  def method
    raise 'foobar'
  end
  
  errors = []
  2.times do
    Thread.new do
      begin
        method
      rescue => e
        errors << e
      end
    end.join
  end
  
  errors[-2] == errors[-1]             # => false

SystemStackError
----------------
SystemStackError is no longer a StandardError. See [[ruby-talk:89782]].

ruby 1.9.0:
  SystemStackError.ancestors                   # => [SystemStackError, Exception, Object, Kernel, BasicObject]

ruby 1.8.6:
  SystemStackError.ancestors                   # => [SystemStackError, StandardError, Exception, Object, Kernel]

Exception#to_str removed [Ruby2]
--------------------------------
ruby 1.9.0:
  p begin
     raise "foo"
  rescue
     $!.to_str
  end 
  # ~> -:4:in `rescue in <main>': undefined method `to_str' for #<RuntimeError: foo> (NoMethodError)
  # ~> 	from -:1:in `<main>'

ruby 1.8.6:
  p begin
     raise "foo"
  rescue
     $!.to_str
  end 
  # >> "foo"

Enumerable and Enumerator
=========================

Enumerator available by default
-------------------------------
Enumerator is now integrated in the core and need not be required.

Enumerable#cycle
----------------
Calls the given block for each element of the enumerable in a
never-ending cycle:

  a = ["a", "b", "c"]
  a.cycle {|x| puts x }  # print, a, b, c, a, b, c,.. forever.
Enumerable#cycle can be described in Ruby as follows
(modulo the enumerator magic):

  def cycle
    a = []
    each{|x| a << x; yield x}
    loop{ a.each{|x| yield x} }
  end

The elements contained in the enumerable are saved in an internal array,
so the #each method is only called once.

Enumerable#each_with_index
--------------------------
Now forwards arguments to #each.

ruby 1.9.0:
  class X
    include Enumerable
    def each(*args); yield args.inspect end
  end
  
  z = nil
  X.new.each_with_index(42){|x| z = x}
  z                                                   # => "[42]"

ruby 1.8.6:
  class X
    include Enumerable
    def each(*args); yield args.inspect end
  end
  
  z = nil
  X.new.each_with_index(42){|x| z = x}
  z                                                   # => 
  # ~> -:7:in `each_with_index': wrong number of arguments (1 for 0) (ArgumentError)
  # ~> 	from -:7

Enumerable#first(n)
-------------------
Gets the first n elements from an enumerable object.

ruby 1.9.0:
  a = {1 => "foo", 2 => "bar", 3 => "babar"}
  a.first(2)                    # => [[1, "foo"], [2, "bar"]]

Enumerable#group_by
-------------------
Groups the values in the enumerable according to the value returned by
the block.

ruby 1.9.0:
  (1..10).group_by{|x| x % 3}   # => {1=>[1, 4, 7, 10], 2=>[2, 5, 8], 0=>[3, 6, 9]}

Enumerable#find_index
---------------------
Similar to #find but returns the index of the first matching element
([[ruby-talk:178495]]).

ruby 1.9.0:
  (1..10).find_index{|x| x % 5 == 0}                # => 4
  (1..10).find_index{|x| x % 25 == 0}               # => nil

Enumerable#take
---------------
Returns either the first n elements from the enumeration or all elements
until the given block returns false ([[ruby-dev:30407]]).

ruby 1.9.0:
  a = [1, 2, 3, 4, 5]
  
  a.take(3)             # => [1, 2, 3]
  a.take {|i| i < 3 }   # => 
  # ~> -:4:in `take': wrong number of arguments(0 for 1) (ArgumentError)
  # ~> 	from -:4:in `<main>'

Enumerable#drop
---------------
Without a block, returns an array with all but the first n elements from
the enumeration. Otherwise drops elements while the block returns true
(and returns all the elements after it returns a false value)
([[ruby-dev:30407]]).

ruby 1.9.0:
  a = [1, 2, 3, 4, 5]
  
  a.drop(3)             # => [4, 5]
  a.drop {|i| i < 3 }   # => 
  # ~> -:4:in `drop': wrong number of arguments(0 for 1) (ArgumentError)
  # ~> 	from -:4:in `<main>'

Enumerable#each
---------------
Returns self if no block is given

ruby 1.9.0:
  a = 4.times
  a = a.each
  a.inject{|s,x| s+x}                               # => 6

Enumerable methods called without a block
-----------------------------------------
If no block is given to the methods in Enumerable (and those in Array,
Dir, Hash, IO, Range, String or Struct that serve the same purposes), an
Enumerator will be generated.

ruby 1.9.0:
  [1,2,3].map           # => #<Enumerable::Enumerator:0xb7b58b20>
  [1,2,3].map.each{|x| p x} # => [1, 2, 3]
  # >> 1
  # >> 2
  # >> 3

Enumerable#inject (#reduce) without a block
-------------------------------------------
If no block is given, the first argument to #inject is the name of a
two-argument method that will be called; the optional second argument is
the initial value.

ruby 1.9.0:
  (1..10).reduce(:+)                                # => 55

Enumerable#count
----------------
It could be defined in Ruby as
 def count(*a)
   inject(0) do |c, e|
     if a.size == 1          # suspect, but this is how it works
       (a[0] == e) ? c + 1 : c
     else
       yield(e) ? c + 1 : c
     end
   end
 end
See [[ruby-dev:26895]].

ruby 1.9.0:
  ["bar", 1, "foo", 2].count(1)                          # => 1
  ["bar", 1, "foo", 2].count{|x| x.to_i != 0}            # => 2

Enumerable#reduce
-----------------
An alias for #inject.

Enumerator#with_index [EXPERIMENTAL]
------------------------------------
You can turn an Enumerator into another that provides the index when
iterating. See [[ruby-talk:147728]].

ruby 1.9.0:
  [1,2,3,4,5,6].map.with_index{|x,i|[2,5].include?(i) ? x : x*2}                # => [2, 4, 3, 8, 10, 6]

Enumerable#min_by, #max_by
--------------------------
ruby 1.9.0:
  %w[1 3 5 7 6 4 2].min_by{|x| 10 - x.to_i}             # => "7"
  %w[1 3 5 7 6 4 2].max_by{|x| 10 - x.to_i}             # => "1"

Enumerable#zip
--------------
Doesn't convert the arguments to arrays; enumerators are used instead.

Second argument to Regexp#match, String#match
---------------------------------------------
Second argument to #match to specify the starting position of the
matching attempt. See [[ruby-core:03203]] and [[ruby-core:03205]].

ruby 1.9.0:
  "foo bar".match(/S+/,3)[0]           # => 
  /S+/.match("foo bar",3)[0]           # => 
  # ~> -:1:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)

Block passed to Regexp#match, String#match
------------------------------------------
If a block is given, it will only be evaluated and given the matchdata
if there is a match.

Enumerable#minmax and minmax_by
-------------------------------
Returns both the minimun and the maximum at once as a two-element array.

Enumerator#rewind
-----------------
Rewinds the enumeration sequence.

Fiber: coroutines/micro-threads
===============================

Fiber
-----
Think of Fibers are threads without preemption.
Fiber#yield can be used to force a change of context amongst
micro-threads.  The API is being refined.  (To be expanded).

Array

Array#nitems
------------
It is equivalent to selecting the elements that satisfy a condition and
obtaining the size of the resulting array. See [[ruby-talk:134083]].

ruby 1.9.0:
  %w[1 2 3 4 5 6].nitems{|x| x.to_i > 3}         # => 3
  %w[1 2 3 4 5 6].nitems{|x| x.to_i > 3}         # => 3

ruby 1.8.6:
  %w[1 2 3 4 5 6].nitems{|x| x.to_i > 3}         # => 6
  %w[1 2 3 4 5 6].nitems{|x| x.to_i > 3}         # => 6

Array#[m,n] = nil doesn't delete elements
-----------------------------------------
It used to delete the selected elements in 1.8.

ruby 1.9.0:
  a = %w[a b c d]
  a[1,2] = nil
  a              # => ["a", nil, "d"]

ruby 1.8.6:
  a = %w[a b c d]
  a[1,2] = nil
  a              # => ["a", "d"]

Block argument to Array#index, Array#rindex [Ruby2]
---------------------------------------------------
They can now take a block to make them work like ''#select''.
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/113069

ruby 1.9.0:
  ['a','b','c'].index{|e| e == 'b'}              # => 1
  ['a','b','c'].index{|e| e == 'c'}              # => 2
  ['a','a','a'].rindex{|e| e == 'a'}             # => 2
  ['a','a','a'].index{|e| e == 'b'}              # => nil

Array#combination
-----------------
ary.combination(n){|c| ...} yields all the combinations of length n of
the elements in the array to the given block. If no block is passed, it
returns an enumerator instead.  The order of the combinations is
unspecified. See [[ruby-list:42671]].

ruby 1.9.0:
  a = [1, 2, 3, 4]
  a.combination(1).to_a  #=> [[1],[2],[3],[4]]
  a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
  a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
  a.combination(4).to_a  #=> [[1,2,3,4]]
  a.combination(0).to_a  #=> [[]]: one combination of length 0
  a.combination(5).to_a  #=> []  : no combinations of length 5

Array#permutation
-----------------
Operates like #combination, but with permutations of length n.

ruby 1.9.0:
  a = [1, 2, 3]
  a.permutation(1).to_a  #=> [[1],[2],[3]]
  a.permutation(2).to_a  #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
  a.permutation(3).to_a  #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
  a.permutation(0).to_a  #=> [[]]: one permutation of length 0
  a.permutation(4).to_a  #=> []  : no permutations of length 4

Array#product
-------------
Returns the cartesian product of the receiver and the arrays given as
arguments.

ruby 1.9.0:
  [1,2,3].product([4,5])     # => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
  [1,2].product([1,2])       # => [[1, 1], [1, 2], [2, 1], [2, 2]]
  [1,2].product([3,4],[5,6]) # => [[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
                             #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
  [1,2].product()            # => [[1], [2]]
  [1,2].product([])          # => []

Argument to Array#pop, Array#shift
----------------------------------
They can take an argument to specify how many objects to return:

ruby 1.9.0:
  %w[a b c d].pop(2)             # => ["c", "d"]

Array#to_s is equivalent to Array#inspect
-----------------------------------------
ruby 1.9.0:
  [1,2,3,4].to_s                                    # => "[1, 2, 3, 4]"

ruby 1.8.6:
  [1,2,3,4].to_s                                    # => "1234"

Array.try_convert
-----------------
Returns either the converted value, as returned by to_ary, or nil if
the object cannot be converted for any reason.

Hash

Hash preserves insertion order
------------------------------
ruby 1.9.0:
  h={:a=>1, :b=>2, :c=>3, :d=>4}  # => {:a=>1, :b=>2, :c=>3, :d=>4}
  h[:e]=5
  h                 # => {:a=>1, :b=>2, :c=>3, :d=>4, :e=>5}
  h.keys            # => [:a, :b, :c, :d, :e]
  h.values          # => [1, 2, 3, 4, 5]
  h.to_a            # => [[:a, 1], [:b, 2], [:c, 3], [:d, 4], [:e, 5]]

ruby 1.8.6:
  h={:a=>1, :b=>2, :c=>3, :d=>4}  # => {:a=>1, :b=>2, :c=>3, :d=>4}
  h[:e]=5
  h                 # => {:a=>1, :e=>5, :b=>2, :c=>3, :d=>4}
  h.keys            # => [:a, :e, :b, :c, :d]
  h.values          # => [1, 5, 2, 3, 4]
  h.to_a            # => [[:a, 1], [:e, 5], [:b, 2], [:c, 3], [:d, 4]]

Hash#to_s is equivalent to Hash#inspect
---------------------------------------
ruby 1.9.0:
  {1,2,3,4}.to_s                                    # => 
  # ~> -:1: syntax error, unexpected ',', expecting tASSOC
  # ~> ..._1198679089_21175_571841 = ({1,2,3,4}.to_s                  ...
  # ~> ...                               ^

ruby 1.8.6:
  {1,2,3,4}.to_s                                    # => "1234"

Hash#compare_by_identity and Hash#compare_by_identity?
------------------------------------------------------
Hash#compare_by_identity lets the hash compare its keys by their
identity (using equal?  instead of eql?).

ruby 1.9.0:
  "a".eql? "a"   # => true
  "a".equal? "a"   # => false
  h1 = { "a" => 100, "b" => 200, :c => "c" }
  h1["a"]        # => 100
  h1.compare_by_identity
  h1.compare_by_identity?  # => true
  # different objects.
  h1["a"]        # => nil
  # same symbols are all the same.
  h1[:c]         # => "c"

Arguments yielded by Hash#each and Hash#each_pair
-------------------------------------------------
#each_pair passes two arguments to the block, #each passes a two-element
array to the block. Keep in mind that |x| is equivalent to |x,|.

ruby 1.9.0:
  {1 => 2}.each{|x| p x}
  {1 => 2}.each_pair{|x| p x}
  # >> [1, 2]
  # >> [1, 2]

ruby 1.8.6:
  {1 => 2}.each{|x| p x}
  {1 => 2}.each_pair{|x| p x} # !> multiple values for a block parameter (2 for 1)
  # >> [1, 2]
  # >> [1, 2]

Return value of Hash#select
---------------------------
Returns a hash instead of an association array ([[ruby-core:11504]]):

ruby 1.9.0:
  {'foo'=>'bar','baz'=>'qux'}.select{|k,v| k=='baz' }    # => {"baz"=>"qux"}

ruby 1.8.6:
  {'foo'=>'bar','baz'=>'qux'}.select{|k,v| k=='baz' }    # => [["baz", "qux"]]

Hash#try_convert
----------------
Returns either the converted value, as returned by to_hash, or nil if
the object cannot be converted for any reason.

Integer
=======

Integer(nil) raises TypeError
-----------------------------
See [[ruby-talk::210205]].

Integer#odd?, #even?
--------------------
ruby 1.9.0:
  1.odd?                                 # => true
  2.odd?                                 # => false

Integer#pred
------------
The opposite of Integer#succ.

Method
======

Method#receiver
---------------
Returns the receiver of a Method object.

ruby 1.9.0:
  class A; def foo; end end
  a = A.new
  a.method(:foo).receiver                           # => #<A:0xb7bb14a0>

Method#name
-----------
Returns the method name.

Method#owner
------------
Returns the class or module where the method was defined.

ruby 1.9.0:
  class A; def foo; end end
  a = A.new
  a.method(:foo).owner                              # => A

Numeric
=======

Numeric#upto, #downto, #times, #step
------------------------------------
These methods return an enumerator if no block is given:

ruby 1.9.0:
  a = 10.times
  a.inject{|s,x| s+x }                  # => 45
  a = []
  b = 10.downto(5)
  b.each{|x| a << x}
  a                                     # => [10, 9, 8, 7, 6, 5]

Numeric#scalar?, Complex#scalar?
--------------------------------
Returns true for non-complex values.  See [[ruby-dev:27936]].

ruby 1.9.0:
  3.scalar?                                          # => true
  3.3.scalar?                                        # => true
  require 'complex'
  Complex.new(0,1).scalar?                           # => false

Numeric#div
-----------
Now uses #floor instead of the previous special cased integer
conversion.  This leads to less surprising behavior at times.
See [[ruby-dev:27674]].

ruby 1.9.0:
  -10.0.div(3)                                      # => -4
  -10.div(3)                                        # => -4

ruby 1.8.6:
  -10.0.div(3)                                      # => -4
  -10.div(3)                                        # => -4

Numeric#fdiv
------------
An alias for quo ([[ruby-dev:30771]]).

Range

Range#cover?
------------
range.cover?(value) compares value to the begin and end values of the
range, returning true if it is comprised between them, honoring
#exclude_end?. See http://www.rubyist.net/~matz/20051210.html#c08 
and [[ruby-talk:167182]].

ruby 1.9.0:
  ("a".."z").cover?("c")                            # => true
  ("a".."z").cover?("5")                            # => false

Range#include?
--------------
When the begin and end values are Numeric types, range.include?(value)
will compare value to them, thus behaving like range.cover?(value).
"Discrete" membership is used for other values:

ruby 1.9.0:
  class A < Struct.new(:v)
    def <=>(o); v <=> o.v end
    def succ; puts v; A.new(v+1) end
  end
  
  (A.new(0)...A.new(2)).include? A.new(2)            # => false
  puts "----"
  (A.new(0)...A.new(2)).include? A.new(1)            # => true
  # >> 0
  # >> 1
  # >> ----
  # >> 0

ruby 1.8.6:
  class A < Struct.new(:v)
    def <=>(o); v <=> o.v end
    def succ; puts v; A.new(v+1) end
  end
  
  (A.new(0)...A.new(2)).include? A.new(2)            # => false
  puts "----"
  (A.new(0)...A.new(2)).include? A.new(1)            # => true
  # >> ----

Range#min, Range#max
--------------------
The operation is now defined in terms of #<=>, instead of iterating
through the members. However, if the range excludes the end value, the
iterative test will be used unless the latter is an Integer.
See [[ruby-talk:167420]].

ruby 1.9.0:
  class A < Struct.new(:v)
    def <=>(o); v <=> o.v end
    def succ; puts v; A.new(v+1) end
  end
  
  (A.new(0)...A.new(2)).min                         # => #<struct A v=0>
  puts "----"
  (A.new(0)..A.new(2)).max                         # => #<struct A v=2>
  puts "----"
  (A.new(0)...A.new(2)).max                         # => #<struct A v=1>
  # >> 1
  # >> ----
  # >> ----
  # >> 0
  # >> 1

ruby 1.8.6:
  class A < Struct.new(:v)
    def <=>(o); v <=> o.v end
    def succ; puts v; A.new(v+1) end
  end
  
  (A.new(0)...A.new(2)).min                         # => #<struct A v=0>
  puts "----"
  (A.new(0)..A.new(2)).max                         # => #<struct A v=2>
  puts "----"
  (A.new(0)...A.new(2)).max                         # => #<struct A v=1>
  # >> 1
  # >> 0
  # >> 1
  # >> ----
  # >> 0
  # >> 1
  # >> ----
  # >> 0
  # >> 1

Regexp
======

Regexp#=== matches symbols
--------------------------
ruby 1.9.0:
  sym = :foo
  # ...
  x = case sym
  when /bar/; 1
  when /foo/; 2
  end
  x                                                # => 2

ruby 1.8.6:
  sym = :foo
  # ...
  x = case sym
  when /bar/; 1
  when /foo/; 2
  end
  x                                                # => nil

Regexp.try_convert
------------------
Returns either the converted value, as returned by to_regexp, or nil if
the object cannot be converted for any reason.

String
======

String is no longer Enumerable
------------------------------
String is not Enumerable anymore. Use #each_line instead of #each, and
#lines (see below) to iterate over the lines.

Encoding-awareness of Strings
-----------------------------
String methods operate on chars and are thus encoding-aware. These are
some of the affected methods:
* ==
* [] []=
* each_line, each_char
* hash
* inspect
* length
* ljust, rjust, center
* reverse
* split
* strip!, strip, lstrip, rstrip
* succ
* upcase, downcase, capitalize, swapcase

The length field in the format specifier for printf-like methods also
operates on a character basis.

String#clear
------------
ruby 1.9.0:
  a = "foo"
  a.clear
  a                # => ""

ruby 1.8.6:
  a = "foo"
  a.clear
  a                # => 
  # ~> -:2: undefined method `clear' for "foo":String (NoMethodError)

One-char-wide semantics for String#[] and String#[]= [Ruby2]
------------------------------------------------------------
Indexing a String with an integer doesn't return a byte value, but a
one-character String. String#[]= changed accordingly:

ruby 1.9.0:
  "a"[0]               # => "a"
  foo = "foo"
  foo[0] = ?a
  foo                  # => "aoo"

ruby 1.8.6:
  "a"[0]               # => 97
  foo = "foo"
  foo[0] = ?a
  foo                  # => "aoo"

String#each_char
----------------
Passes each character (not byte!) to the given block.

String#ord
----------
The new String#ord allows you to get your friendly Fixnum out of the
String returned by String#[], so
 'a'[0].ord    # => 97
is equivalent the 'a'[0] in 1.8.

String#partition, #rpartition
-----------------------------
str.partition(sep) returns an array with
* the text before the first occurrence of sep in str
* the separator
* the text after the separator
If sep cannot be found in str, it will return [str, "", ""]. sep can be
a String or a Regexp.

rpartition is similar to #partition but the text is cut at the last
occurrence of the separator in the string.

ruby 1.9.0:
  "hello".partition("l")                            # => ["he", "l", "lo"]
  "hello".rpartition("l")                           # => ["hel", "l", "o"]
    
  "abcdedcbabcdcba".partition(/cd/)                 # => ["ab", "cd", "edcbabcdcba"]
  "abcdedcbabcdcba".rpartition(/cd/)                # => ["abcdedcbab", "cd", "cba"]

String#lines
------------
Returns an enumerator that will yield each line in the string.
String#lines accepts an extra argument to indicate the line separator.
If given a block, #lines behaves like #each_line ([[ruby-core:9218]]).

ruby 1.9.0:
  "foo\nbar".lines.sort                             # => ["bar", "foo\n"]

String#bytes
------------
Returns an enumerator that will yield each byte in the string:

ruby 1.9.0:
  "hello".bytes.to_a             # => [104, 101, 108, 108, 111]

String#encoding
---------------
Returns the encoding of the string.

String#force_encoding
---------------------
Changes the encoding of the string to the given one and returns self.

String#start_with?, #end_with?
------------------------------
string.start_with?(str) returns true if str is a prefix (suffix) of
string.

String#unpack with a block
--------------------------
If given a block, String#unpack will call it with the unpacked values
instead of creating an array.

ruby 1.9.0:
  s = (0..4).to_a.pack("V*")
  a = []
  s.unpack("V*"){|x| a << x}
  a                                                 # => [0, 1, 2, 3, 4]

ruby 1.8.6:
  s = (0..4).to_a.pack("V*")
  a = []
  s.unpack("V*"){|x| a << x}
  a                                                 # => []

String#hash
-----------
Now uses Bob Jenkins' hash.

String#upto
-----------
Takes an optional second array specifying whether the to exclude
the final value (by default, it is included).

String.try_convert
------------------
Returns either the converted value, as returned by to_string, or nil if
the object cannot be converted for any reason.

Zero-length symbols allowed
---------------------------
ruby 1.9.0:
  "".intern                    # => 
  :""                          # ~>  empty symbol literal # !> useless use of nil in void context
  # ~> -:2: empty symbol literal
  # ~> :""                          # ~>  empty symbol literal
  # ~>    ^

ruby 1.8.6:
  "".intern                    # => 
  :""                          # ~>  empty symbol literal
  # ~> -:2: empty symbol literal
  # ~> :""                          # ~>  empty symbol literal
  # ~>    ^

Struct
======

Struct#inspect
--------------
Does not show the class name for anonymous structs:

ruby 1.9.0:
  Struct.new(:a).new("")                            # => #<struct a="">

ruby 1.8.6:
  Struct.new(:a).new("")                            # => #<struct #<Class:0xb7dbd334> a="">

Symbol
======

Symbol#=== matches strings
--------------------------
ruby 1.9.0:
  :a === "a"                                        # => true

ruby 1.8.6:
  :a === "a"                                        # => false

Symbol#intern
-------------
Returns self.

Symbol#encoding
---------------
Returns the encoding of the symbol.

Symbol methods similar to those in String
-----------------------------------------
Now Symbols respond to many methods that resemble those in String:
* []
* <=>, casecmp, =~, ===
* empty?
* encoding
* length, size
* match
* slice
* succ, next
* upcase, downcase, capitalize, swapcase

Math

Math#log and Math#log2
----------------------
Math#log accepts an optional base argument ([[ruby-talk:191308]]).  The
new method Math#log2 ([[ruby-talk:191237]]) computes the base 2
logarithm.

File and Dir operations
=======================

to_path called in file operations [Ruby2]
-----------------------------------------
The to_path method will be called for for non-String arguments in
File.path, File.chmod, File.lchmod, File.chown, File.lchown,
File.utime, File.unlink...

ruby 1.9.0:
  File.path(Struct.new(:path){ def to_path; path end }.new("foo"))        # => "foo"

ruby 1.8.6:
  File.path(Struct.new(:path){ def to_path; path end }.new("foo"))        # => 
  # ~> -:1: undefined method `path' for File:Class (NoMethodError)

Dir.[], Dir.glob
----------------
* ''['' is no longer considered a normal char ([[ruby-dev:23291]]):
* handling of escaped '{', '}' and ',' ([[ruby-dev:23376]]):

ruby 1.9.0:
  File.open("/tmp/[", "w"){|f| f.puts "hi"}
  Dir["/tmp/["]                # => []
---
  File.open("/tmp/,", "w"){|f| f.puts "hi"}
  Dir.glob('/tmp/{\,}')                # => ["/tmp/,"]

ruby 1.8.6:
  File.open("/tmp/[", "w"){|f| f.puts "hi"}
  Dir["/tmp/["]                # => []
---
  File.open("/tmp/,", "w"){|f| f.puts "hi"}
  Dir.glob('/tmp/{\,}')                # => ["/tmp/,"]

Dir.exist?
----------
Equivalent to File.directory?.

Dir#inspect
-----------
File::world_readable?
---------------------
File::world_writable?
---------------------
Pathname#world_readable?
------------------------
Pathname#world_writable?
------------------------
File::Stat#world_readable?
--------------------------
File::Stat#world_writable?
--------------------------
FileUtils.copy_entry
--------------------
IO operations
=============

Non-blocking IO
---------------
Lots of new methods for non-blocking IO: IO#read_nonblock,
IO#write_nonblock, Socket#connect_nonblock, Socket#accept_nonblock,
Socket#revcfrom_nonblock [[ruby-core:7917]],
IPSocket#recvfrm_nonblock, UNIXSocket#recvfrom_nonblock,
TCPServer#accept_nonblock, UNIXServer#accept_nonblock.

IO#getc
-------
Now returns a single-char String instead of an Integer.

IO#getbyte, IO#readbyte, StringIO#getbyte, StringIO#readbyte
------------------------------------------------------------
getbyte returns either a Fixnum or nil on EOF.
readbyte returns a Fixnum or raises EOFError.

Kernel#open [Ruby2]
-------------------
Uses #to_open if the first argument responds to it.

ruby 1.9.0:
  require 'stringio'
  sio = StringIO.new("fooooo")
  s = Struct.new(:io){ def to_open; io end }.new(sio)
  open(s){|io| io.gets }                # => "fooooo"

IO#initialize now accepts an IO argument
----------------------------------------
See [[ruby-dev:22195]].

ruby 1.9.0:
  IO.new(STDOUT).fileno                # => 1

StringIO#readpartial
--------------------
It is an alias for ''StringIO#sysread''.

ruby 1.9.0:
  require 'stringio'
  StringIO.new("foo").readpartial(2)                # => "fo"

IO#lines
--------
Returns an enumerator that will return each line in the IO (similar to
String#lines).

IO#bytes
--------
Returns an enumerator that will return each byte in the IO (similar to
String#bytes).

IO.try_convert
--------------
Returns either the converted value, as returned by to_io, or nil if
the object cannot be converted for any reason.

Limit input in IO and StringIO operations
-----------------------------------------
IO#gets, IO#readline, IO#readlines, IO#each_line, IO#lines, IO.foreach,
IO.readlines, StringIO#gets, StringIO#readline, StringIO#each and
StringIO#readlines accept an optional integer argument to specify the
maximum amount of data to be read. The limit is specified either as the
(optional) second argument, or by passing a single integer argument
(i.e. the first argument is interpreted as the limit if it's an integer,
 as a line separator otherwise).

IO#ungetc, StringIO#ungetc
--------------------------
They allow to push back an arbitrarily large character.

Time

Time#monday?...sunday?
----------------------
Seven predicate methods where added for the weekdays
([[ruby-list:41340]]).

ruby 1.9.0:
  Time.now                # => 2007-12-26 23:24:51 +0900
  Time.now.sunday?                # => false

New format in Time#to_s
-----------------------
ruby 1.9.0:
  Time.new.to_s                                     # => "2007-12-26 23:24:51 +0900"

ruby 1.8.6:
  Time.new.to_s                                     # => "Wed Dec 26 23:24:51 +0900 2007"

Timezone information preserved on Marshal.dump/load
---------------------------------------------------
See [[ruby-talk:100213]].

ruby 1.9.0:
  class Object
    def deep_copy
      Marshal.load(Marshal.dump(self))
    end
  end
  fmt = "%m-%d-%Y %H:%M"
  original = Time.gm(2004, 04, 25, 22, 56)                # => 2004-04-25 22:56:00 UTC
  copy = original.deep_copy                # => 2004-04-25 22:56:00 UTC

ruby 1.8.6:
  class Object
    def deep_copy
      Marshal.load(Marshal.dump(self))
    end
  end
  fmt = "%m-%d-%Y %H:%M"
  original = Time.gm(2004, 04, 25, 22, 56)                # => Sun Apr 25 22:56:00 UTC 2004
  copy = original.deep_copy                # => Mon Apr 26 07:56:00 +0900 2004

Process
=======

Process.setrlimit
-----------------
Used as 
  Process.setrlimit(resource, cur_limit, max_limit)
The resources are OS-dependent, but SuSv3 defines a number of them,
allowing to set stack size, file descriptor, core size, data segment
size, CPU time limits...  See [[ruby-dev:24834]].

The third argument is optional.

Process.daemon
--------------
Process.daemon()                        => fixnum
Process.daemon(nochdir=nil,noclose=nil) => fixnum

Detach the process from controlling terminal and run in
the background as system daemon.  Unless the argument
nochdir is true (i.e. non false), it changes the current
working directory to the root ("/"). Unless the argument
noclose is true, daemon() will redirect standard input,
standard output and standard error to /dev/null.

Process.exec
------------
It is to Process.fork what execv(3) is to fork(2). [[ruby-dev:28107]]

Symbols
=======

Symbols: restriction on literal symbols
---------------------------------------
See [[ruby-core:02518]].
Symbols for invalid global variable (e.g. `:$-)`) aren't allowed.
 :$-)        # =>  # !> useless use of a literal in void context
 # ~> -:1: syntax error, unexpected ')', expecting $end
 # ~>  :$-)        # => 
 # ~>      ^
however
 "$-)".to_sym # => :"$-)"

$SAFE

$SAFE and bound methods
-----------------------
$SAFE isn't set for methods defined from Proc.  
See http://www.rubyist.net/~nobu/t/20040611.html and [[ruby-dev:23697]].

Miscellaneous new methods
=========================

GC.stress, GC.stress=
-/tmp/ruby-changelog.20784.17:1:in `<main>': undefined method `to_a' for 1:Fixnum (NoMethodError)
--------------------
GC is done on every memory allocation when  
 GC.stress = true
This is useful to debug Ruby extensions (such as Syck).

Method#hash, Proc#hash
----------------------
See [[ruby-talk:93968]]

ruby 1.9.0:
  lambda{}.hash;                # => 1068450039
  lambda{}.hash;                # => 1068447431
  method(:object_id).hash                # => 162308
  method(:object_id).hash                # => 162308

Symbol#to_proc
--------------
The infamous &:proc trick.

ruby 1.9.0:
  %w[dsf fgdg fg].map(&:capitalize)  # => ["Dsf", "Fgdg", "Fg"]

Deprecation
===========

VERSION and friends
-------------------
Use RUBY_VERSION, RUBY_RELEASE_DATE... instead.

StringScanner#peep, empty, clear
--------------------------------
The StringScanner methods #peep, #empty, #clear and #getbyte have been
renamed to #peek, #eos?, #terminate and #get_byte.

Kernel.to_a
-----------
ruby 1.9.0:
  1.to_a                # => 
  nil.to_a                # => 
  # ~> -:1:in `<main>': undefined method `to_a' for 1:Fixnum (NoMethodError)

ruby 1.8.6:
  1.to_a                # => [1] # !> default `to_a' will be obsolete
  nil.to_a                # => []

Kernel#getc
-----------
Replaced by STDIN.getc.

Object#type
-----------
Gone for good, see [[ruby-core:04335]].

ruby 1.9.0:
  "".type                # => 
  # ~> -:1:in `<main>': undefined method `type' for "":String (NoMethodError)

ruby 1.8.6:
  "".type                # => String # !> Object#type is deprecated; use Object#class

File.exists?
------------
Use File.exist? instead.

Hash#index
----------
Use Hash#key.

ruby 1.9.0:
  p({a: 1, b: 2}.key(2))
  # >> :b

ENV.index
---------
ENV replicates Hash's behaviour. See [[ruby-dev:25974]].

ruby 1.9.0:
  ENV["foo"] = "someuniqueval"
  ENV.index("someuniqueval")                # => "foo" # !> ENV.index is deprecated; use ENV.key

ruby 1.8.6:
  ENV["foo"] = "someuniqueval"
  ENV.index("someuniqueval")                # => "foo"

Symbol#to_int
-------------
ruby 1.9.0:
  :foo.to_int                         # => 
  # ~> -:1:in `<

Invalid change descriptions
===========================

Module#class_variable_defined?
------------------------------
Expected something different from true

Passing blocks to []
--------------------
Expected ["3445", 16], got nil.

NameError
---------
Expected false, got true.

__method__ and __callee__
-------------------------
Expected [:foo, :bar], got [:foo, :foo].

main>': undefined method `to_int' for :foo:Symbol (NoMethodError)

ruby 1.8.6:
  :foo.to_int                         # => 10529 # !> treating Symbol as an integer

Array and Hash indices, indexes
-------------------------------