Changes in Ruby 1.9
Last major update on 2006-06-11.
I have scanned over 25000 lines of Changelogs to extract the changes between the stable branch and HEAD. These include important syntax additions, lots of modifications in the behavior of Procs and lambdas, new Enumerator and Enumerable goodies, convenient methods to interact with the OS, new IO stuff…
This is not Ruby 2.0!
Keep in mind that Ruby HEAD is being used to try wild and weird ideas. It should by no means be understood as a final say on what Ruby 2.0 will be like. A few decisions are firm and were labelled as Ruby2 in the Changelogs by matz. The below list also includes many crazy ideas (marked as EXPERIMENTAL in the Changelogs and here) which will probably be dropped in short.
Preliminary notes
- this is, by necessity, work in progress, as Ruby 1.9 keeps evolving; I’ll try to keep it up-to-date.
- the snippets which include the resulting value in a comment were evaluated using my XMP filter, under ruby 1.9.0 unless otherwise stated. The 1.8 interpreter used was ruby 1.8.4.
Table of contents
- Table of contents
- New syntax and semantics
- New constant lookup rules
- New literal hash syntax [Ruby2]
- Block local variables [EXPERIMENTAL]
- New syntax for lambdas [VERY EXPERIMENTAL]
- Calling Procs without #call/#[] [EXPERIMENTAL]
- Block arguments
- Multiple splats allowed
- ?c semantics
- Arguments to #[]
- printf-style formatted strings (%)
- Kernel and Object
- Class and Module
- Module#const_defined?, #const_get and #method_defined?
- #class_variable_{set,get}
- Class of singleton classes
- Class variables
- #module_exec
- Extra subclassing check when binding UnboundMethods
- Binding#eval
- Blocks and Procs
- Proc#yield
- Arity of blocks without arguments
- Passing blocks to #[]
- proc is now a synonym of Proc.new
- Exceptions
- Enumerable and Enumerator
- Enumerable#first(n)
- Enumerable#group_by
- Enumerable#find_index
- Enumerator#each
- Enumerable methods called without a block
- Enumerable#count
- Enumerator#with_index [EXPERIMENTAL]
- Added #min_by, #max_by
- Regexp#match, String#match
- Array
- Array#nitems
- Array#[m,n] = nil places nil in the array.
- Block argument to Array#index, Array#rindex [Ruby2]
- Array#pop, Array#shift
- Numeric
- Range
- String
- Math
- File and Dir operations
- #to_path in File.path, File.chmod, File.lchmod, File.chown, File.lchown, File.utime, File.unlink… [Ruby2]
- Dir.[], Dir.glob
- New methods
- IO operations
- Non-blocking IO
- IO#getc
- Kernel#open [Ruby2]
- IO#initialize now accepts an IO argument
- StringIO#readpartial
- Time
- Process
- Symbols: restriction on literal symbols
- $SAFE and bound methods
- Misc. new methods
- Deprecation
New syntax and semantics
New constant lookup rules
Now constants are looked up in the following order:
- current class
- super classes except Object
- lexically enclosing classes/modules
- Object
The new rules entail differences in dynamic constant lookups too:
class A
BAR = 1
def foo(&b); instance_eval(&b) end
end
a = A.new
a.foo { BAR } # => 1
vs. 1.8:
class A
BAR = 1
def foo(&b); instance_eval(&b) end
end
a = A.new
a.foo { BAR } # =>
# ~> -:7: uninitialized constant BAR (NameError)
# ~> from -:3:in `foo'
# ~> from -:7
See also ruby-talk:181646.
New literal hash syntax [Ruby2]
{a: "foo"} # => {:a=>"foo"}
Block local variables [EXPERIMENTAL]
Used as follows:
# {normal args; local variables}
d = 2
a = lambda{|;d| d = 1}
a.call()
d # => 2
When a variable is shadowed, ruby1.9 issues a warning:
-:2: warning: shadowing outer local variable - d
New syntax for lambdas [VERY EXPERIMENTAL]
a = ->(b,c){ b + c }
a.call(1,2) # => 3
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:
-> { }.call # => nil
-> a, b { a + b }.call(1,2) # => 3
c = 1; -> a, b; c { c = a + b }.call(1,2); c # => 1
It can get very tricky though:
c = 2; -> ;c { c = 1 }.call; c # => 2
or even
c = 2; -> *d ; c { d }.call(1,2,3) # => [1, 2, 3]
c = 2; -> ; c { c = 1 }.call; c # => 2
Calling Procs without #call/#[] [EXPERIMENTAL]
You can now do:
a = lambda{|*b| b}
(a)(1,2) # => [1, 2]
Note that you need the parentheses:
a = lambda{|*b| b}
a(1,2) # => ERROR: (eval):2: compile error...
# (eval):2: syntax error...
# (a)(1,2)...
You can use any expression inside the parentheses:
(lambda{|a,b| a + b})(1,2) # => 3
Block arguments
Blocks can take &block arguments:
define_method(:foo){|&b| b.call(bar)}
ruby-dev:23533
Multiple splats allowed
As suggested by Audrey Tang, 1.9 allows multiple splat operators when calling a method:
def foo(*a)
a
end
foo(1, *[2,3], 4, *[5,6]) # => [1, 2, 3, 4, 5, 6]
?c semantics
?a now returns a single character string instead of an integer:
?a # => "a"
Arguments to #[]
You can use splats, “assocs” (hashes without braces) and block arguments with #[]:
RUBY_VERSION # => "1.9.0"
RUBY_RELEASE_DATE # => "2006-06-11"
class Foo; def [](*a, &block); block.call(a) end end
a = (0..3).to_a
Foo.new[*a, :op => :+]{|x| x } # => [0, 1, 2, 3, {:op=>:+}]
printf-style formatted strings (%)
%c can print a one character String (as returned e.g. by ?c).
Kernel and Object
BasicObject
BasicObject is a top level BlankSlate class:
BasicObject.instance_methods # => ["__send__", "funcall", "__id__", "==", "send", "respond_to?", "equal?", "object_id"] Object.ancestors # => [Object, Kernel, BasicObject]
#instance_exec
Allows to evaluate a block with a given self, while passing arguments:
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
send doesn’t call private methods anymore
ruby-talk:153672 It is still possible to call them with the newly introduced #funcall method.
class Foo; private; def foo; end; end Foo.new.funcall(:foo) # => nil Foo.new.send(:foo) # => ERROR: private method `foo' called for #<Foo:0xb7e0e540>
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.
1 =~ 1 # => nil
ruby-core:05391.
Class and Module
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):
module A; X = 1; def foo; end end module B include A const_defined? "X" # => true method_defined? :foo # => true method_defined? :foo, false # => false const_get "X" # => 1 end
vs. (1.8)
module A; X = 1; def foo; end end module B include A const_defined? "X" # => false method_defined? :foo # => true const_get "X" # => 1 end
#class_variable_{set,get}
They are public in 1.9, private in 1.8:
class B; self end.class_variable_set(:@@a, "foo") # => "foo"
Class of singleton classes
singleton class inherits Class rather than its object’s class
class X;end; x=X.new; class << x; self < X; end # => true
vs. (1.8)
class X;end; x=X.new; class << x; self < X; end # => nil
[ruby-dev:23690]
Class variables
Class variables are not inherited
ruby-dev:23808
class A; @@a = 1; end; class B < A; @@a end # => ERROR: (eval):1: uninitialized class variable @@a in B
vs.
class A; @@a = 1; end; class B < A; @@a end # => 1
#module_exec
Similar to Object#instance_exec.
Extra subclassing check when binding UnboundMethods
class Foo; def foo; end end module Bar define_method(:foo, Foo.instance_method(:foo)) end # => ERROR: (eval):3:in `define_method': bind argument must be a subclass of Foo
ruby-dev:23410
Blocks and Procs
Proc#yield
Proc#yield was added (also NilClass#yield which raises a LocalJumpError so you can use it on &block).
Quoting from the RDoc:
Invokes the block, setting the block's parameters to the values in
params in the same manner the yield statement does.
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}
a_proc.yield(1,2,3) # => [1]
Arity of blocks without arguments
1.8
lambda{}.arity # => -1
1.9
lambda{}.arity # => 0
arity is now defined as number of parameters that would not be ignored
Therefore,
lambda{}.call(1) # => ERROR: (eval):1: wrong number of arguments (1 for 0)
raises an exception (ruby-talk:120253).
See also http://rcrchive.net/rcr/show/227.
Passing blocks to #[]
You can now do things like the following contrived example:
s = "ab34cd45"
def s.[](x, &b); split(//).grep(x).each(&b) end
digits, sum = "", 0
s[/\d/]{|x| digits << x; sum += x.to_i }
[digits, sum] # => ["3445", 16]
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.
proc{|a,b|}.arity # => 2
proc{|a,b|}.call(1) # => nil
Proc.new{|a,b|}.arity # => 2
Proc.new{|a,b|}.call(1) # => nil
vs. (1.8)
proc{|a,b|}.arity # => 2
proc{|a,b|}.call(1) # => ERROR: (eval):1: wrong number of arguments (1 for 2)
Proc.new{|a,b|}.arity # => 2
Proc.new{|a,b|}.call(1) # => nil
Exceptions
NameError
It is now a direct descendent of Exception instead of StandardError, so it is not caught by the default rescue:
"".asdas rescue 1 # =>
- ~> -:1: undefined method `asdas’ for “”:String (NoMethodError)
vs. 1.8:
"".asdas rescue 1 # => 1
Equality of exceptions
They are now considered equal if they have the same class, message and backtrace (ruby-talk:110354).
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
SystemStackError
move SystemStackError from under StandardError to Exception
ruby-talk:89782
SystemStackError < StandardError # => true
Removed Exception#to_str [Ruby2]
begin raise "foo" rescue $!.to_str end # => ERROR: undefined method `to_str' for #<RuntimeError: foo>
Enumerable and Enumerator
Enumerator is now integrated in the core and need not be required.
Enumerable#first(n)
Gets the first n elements from an enumerable object:
a = {1 => "foo", 2 => "bar", 3 => "babar"}
a.first(2) # => [[1, "foo"], [2, "bar"]]
# NOTE: order not preserved in general, just happened to be so
Enumerable#group_by
Groups the values in the enumerable according to the value returned by the block:
(1..10).group_by{|x| x % 3} # => {0=>[3, 6, 9], 1=>[1, 4, 7, 10], 2=>[2, 5, 8]}
Enumerable#find_index
Similar to #find but returns the index of the first matching element (ruby-talk:178495)
(1..10).find_index{|x| x % 5 == 0} # => 4
(1..10).find_index{|x| x % 25 == 0} # => nil
Enumerator#each
Returns self if no block is given:
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:
[1,2,3].map # => #<Enumerable::Enumerator:0xb7d666bc>
[1,2,3].map.each{|x| p x} # => [nil, nil, nil] /// output: '1\n2\n3\n'
Enumerable#count
It could be defined in Ruby as
def count(*a)
inject(0) do |c, e|
unless a.size == 1 # suspect, but this is how it works
(a[0] == x) ? c + 1 : c
else
yield(x) ? c + 1 : c
end
end
end
Therefore
["bar", 1, "foo", 2].count(1) # => 1
["bar", 1, "foo", 2].count{|x| x.to_i != 0} # => 2
ruby-dev:26895
Enumerator#with_index [EXPERIMENTAL]
You can turn an Enumerator into another that provides the index when iterating:
[1,2,3,4,5,6].map.with_index {|x,i|[2,5].include?(i) ? x : x*2} # => [2, 4, 3, 8, 10, 6]
ruby-talk:147728
Added #min_by, #max_by
%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"
Regexp#match, String#match
Second argument to #match to specify the starting position of the matching attempt
"foo bar".match(/\S+/,3)[0] # => "bar"
/\S+/.match("foo bar",3)[0] # => "bar"
ruby-core:03203, ruby-core:03205
Array
Array#nitems
It is equivalent to selecting the elements that satisfy a condition and obtaining the size of the resulting array:
%w[1 2 3 4 5 6].nitems{|x| x.to_i > 3} # => 3
In 1.8, the block was just ignored:
%w[1 2 3 4 5 6].nitems{|x| x.to_i > 3} # => 6 in 1.8
ruby-talk:134083
Array#[m,n] = nil places nil in the array.
It used to delete the selected elements in 1.8.
a = %w[a b c d]; a[1,2] = nil; a # => ["a", nil, "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
['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#pop, Array#shift
They can take an argument to specify how many objects to return:
%w[a b c d].pop(2) # => ["c", "d"]
Numeric
Numeric#upto, #downto, #times
These methods return an enumerator if no block is given:
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.
3.scalar? # => true 3.3.scalar? # => true require 'complex' Complex.new(0,1).scalar? # => false
(ruby-dev:27936)
Numeric#div
Now uses #floor instead of the previous special cased integer conversion. This leads to less surprising behavior at times:
RUBY_VERSION # => "1.9.0" -10.0.div(3) # => -4 -10.div(3) # => -4
vs.
RUBY_VERSION # => "1.8.4" -10.0.div(3) # => -3 -10.div(3) # => -4
(ruby-dev:27674)
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?.
("a".."z").cover?("c") # => true
("a".."z").cover?("5") # => false
(http://www.rubyist.net/~matz/20051210.html#c08 ruby-talk:167182)
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:
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
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.
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> # >> ---- # >> ---- # >> 0 # >> 1
(ruby-talk:167420)
String
String#clear
a = "foo" a.clear a # => ""
“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:
"a"[0] # => 'a' foo = "foo" foo[0] = ?a foo # => 'aoo'
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.
File and Dir operations
#to_path in File.path, File.chmod, File.lchmod, File.chown, File.lchown, File.utime, File.unlink… [Ruby2]
The #to_path method will be called for for non-String arguments.
File.path(Struct.new(:path){ def to_path; path end }.new("foo")) # => "foo"
Dir.[], Dir.glob
- [ is no longer considered a normal char (ruby-dev:23291):
File.open("/tmp/[", "w"){|f| f.puts "hi"}
Dir["/tmp/["] # => []
- handling of escaped ‘{‘, ‘}’ and ‘,’ (ruby-dev:23376):
File.open("/tmp/,", "w"){|f| f.puts "hi"}
Dir.glob('/tmp/{\,}') # => ["/tmp/,"] instead of ["/tmp/", "/tmp/"]
New methods
- 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.
Kernel#open [Ruby2]
Uses #to_open if the first argument responds to it:
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
ruby-dev:22195
IO.new(STDOUT).fileno # => 1
StringIO#readpartial
It is an alias for StringIO#sysread.
require 'stringio'
StringIO.new("foo").readpartial(2) # => "fo"
Time
Seven predicate methods where added for the weekdays (ruby-list:41340):
Time.now # => Thu Nov 03 18:58:25 CET 2005 Time.now.sunday? # => false
Timezone information preserved on Marshal.dump/load
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 # => Sun Apr 25 22:56:00 UTC 2004
instead of
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 00:56:00 CEST 2004
ruby-talk:100213
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: restriction on literal symbols
ruby-core:02518
should not allow symbol for invalid global variable (e.g. `:$-)`).
:$-) # => # !> useless use of a literal in void context # ~> -:1: syntax error, unexpected ')', expecting $end # ~> :$-) # => # ~> ^
however
"$-)".to_sym # => :"$-)"
$SAFE and bound methods
eval.c (proc_set_safe_level, proc_invoke, rb_mod_define_method): not set $SAFE for methods defined from Proc.
See http://www.rubyist.net/~nobu/t/20040611.html and ruby-dev:23697. ruby-dev:23697
Misc. new methods
GC.stress, GC.stress=
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
ruby-talk:93968
lambda{}.hash; # => 3
lambda{}.hash; # => 3
method(:object_id).hash # => 4504
method(:object_id).hash # => 4504
__method__ and __callee__
Return the original (unaliased) and aliased names of the executing method (or nil at the toplevel):
def foo; [__method__, __callee__] end
class << self; self end.module_eval { alias_method :bar, :foo }
foo # => [:foo, :foo]
bar # => [:foo, :bar]
Symbol#to_proc
Allows you to do
%w[dsf fgdg fg].map(&:capitalize) # => ["Dsf", "Fgdg", "Fg"]
Deprecation
VERSION and friends
Use RUBY_VERSION, RUBY_RELEASE_DATE… instead.
StringScanner
The StringScanner methods #peep, #empty, #clear and #getbyte have been renamed to #peek, #eos?, #terminate and #get_byte.
Kernel.to_a
Removed.
1.to_a # => ERROR: undefined method `to_a' for 1:Fixnum
However:
nil.to_a # => []
Object#type
Removed altogether (ruby-core:04335).
"".type # => ERROR: undefined method `type' for "":String
Hash#index
You should now use Hash#key:
{a: 1, b: 2}.key(2) # => :b
ENV.index
ENV replicates Hash‘s behaviour, so
ENV["foo"] = "1"
ENV.index("1") # => "foo"
will issue a warning
-:2: warning: ENV.index is deprecated; use ENV.key
ruby-dev:25974
Symbol#to_int
It’s gone at last.
Compare
RUBY_VERSION # => "1.9.0" :foo.to_int # => # ~> -:2: undefined method `to_int' for :foo:Symbol (NoMethodError)
to
RUBY_VERSION # => "1.8.4" :foo.to_int # => 10273 # !> treating Symbol as an integer
Removed Array and Hash #indices, #indexes
%w[a b c].indices # => ERROR: undefined method `indices' for ["a", "b", "c"]:Array
{1, 2, 3, 4}.indices # => ERROR: undefined method `indices' for {1=>2, 3=>4}:Hash

Keyword(s):[ruby] [1.9] [ruby2] [changelog] [diffable]
References:[Ruby 1.8.5 released. What’s new?] [Changes in Ruby 1.9, second update] [Ruby 1.8.5 in time for the Lantern Festival] [Last month, in Ruby 1.9…] [Dissecting matz’s monster patch: lots of activity in 1.9] [Enhanced xmp code evaluation and annotation] [First update to the Ruby change summary] [Ruby] [Differential RSS feeds]