Changes in Ruby 1.9
Latest news
This changelog will soon be replaced by The mechanically verified Ruby 1.9 changelog.
Last major update on 2007-10-12
I have scanned over 40000 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 were either ruby 1.8.4 or 1.8.5.
Table of contents
- Table of contents
- New syntax and semantics
- New literal hash syntax [Ruby2]
- Block local variables [EXPERIMENTAL]
- Block arguments are always local
- New syntax for lambdas [VERY EXPERIMENTAL]
- .() and calling Procs without #call/#[] [EXPERIMENTAL]
- Block arguments
- News semantics for block arguments
- Method used for splat arguments: #to_splat
- Multiple splats allowed
- Mandatory arguments after optional arguments allowed
- ?c semantics
- Arguments to #[]
- printf-style formatted strings (%)
- Newlines allowed before ternary colon
- defined? and local variables
- Kernel and Object
- BasicObject
- #instance_exec
- send doesn't always call private methods anymore (#__send, #__send!)
- Kernel#require
- Object#=~
- Object#tap
- Kernel#instance_variable_defined?
- Kernel#define_singleton_method
- Kernel#singleton_methods, Kernel#methods
- Class and Module
- Module#instance_methods, #private_instance_methods, #public_instance_methods
- Module#const_defined?, #const_get and #method_defined?
- Module#class_variable_defined?
- #class_variable_{set,get}
- Module#attr is an alias of attr_reader
- 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
- Proc#lambda?
- Exceptions
- Enumerable and Enumerator
- Enumerable#cycle
- Enumerable#each_with_index
- Enumerable#first(n)
- Enumerable#group_by
- Enumerable#find_index
- Enumerable#take
- Enumerable#drop
- Enumerator#each
- Enumerable methods called without a block
- Enumerable#inject (#reduce) without a block
- Enumerable#count
- Enumerable#reduce
- Enumerator#with_index [EXPERIMENTAL]
- Enumerable##min_by, #max_by
- Enumerable#zip
- Regexp#match, String#match
- Fiber: coroutines/micro-threads
- Array
- Array#nitems
- Array#[m,n] = nil places nil in the array.
- Block argument to Array#index, Array#rindex [Ruby2]
- Array#combination
- Array#permutation
- Array#product
- Array#pop, Array#shift
- Array#to_s is equivalent to Array#inspect
- Array.try_convert
- Hash
- Hash preserves order!
- Hash#to_s is equivalent to Hash#inspect
- Hash#_compare_by_identity and Hash#compare_by_identity?
- Semantics for Hash#each and Hash#each_pair
- Hash#select
- Hash.try_convert
- Integer
- Method
- Numeric
- Range
- Regexp
- String
- No longer an Enumerable
- Encoding-awareness
- String#clear
- "One-char-wide" semantics for String#[] and String#[]= [Ruby2]
- String#each_char
- String#ord
- String#partition, #rpartition
- String#lines
- String#bytes
- String#encoding
- String#force_encoding
- String#start_with?, #end_with?
- String#unpack with a block
- String#hash
- String#upto
- String.try_convert
- Zero-length symbols allowed
- Struct
- Symbol
- 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
- Dir.exist?
- New methods
- IO operations
- Non-blocking IO
- IO#getc
- IO#getbyte, IO#readbyte, StringIO#getbyte, StringIO#readbyte
- Kernel#open [Ruby2]
- IO#initialize now accepts an IO argument
- StringIO#readpartial
- IO#lines
- IO#bytes
- IO.try_convert
- Limit input in IO#gets, IO#readline, IO#readlines, IO#each_line, IO#lines, IO.foreach, IO.readlines, StringIO#gets, StringIO#readline, StringIO#each, StringIO#readlines
- IO#ungetc, StringIO#ungetc
- Time
- Process
- Symbols: restriction on literal symbols
- $SAFE and bound methods
- Misc. new methods
- Deprecation
New syntax and semantics
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
Block arguments are always local
a = 1
10.times{|a| } # !> shadowing outer local variable - a
a # => 1
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
.() and calling Procs without #call/#[] [EXPERIMENTAL]
You can now do:
a = lambda{|*b| b}
a.(1,2) # => [1, 2]
Note that you need the period:
a = lambda{|*b| b}
a(1,2) # =>
# (eval):2: syntax error...
# (a)(1,2)...
- ~> -:2: undefined method `a' for main:Object (NoMethodError)
You can use any expression inside the parentheses:
(lambda{|a,b| a + b}).(1,2) # => 3
.() will try to use #call no matter the receiver:
"foo".(1,2) # ~> undefined method `call' for "foo":String (NoMethodError)
Block arguments
Blocks can take &block arguments:
define_method(:foo){|&b| b.call(bar)}
News semantics for block arguments
|v| now works like the former |v,|:
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.8.5", "2006-08-25"]
def m; yield 1, 2; end
m{|v| v} # => [1, 2] # !> multiple values for a block parameter (2 for 1)
vs.
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"]
def m; yield 1, 2; end
m{|v| v} # => 1
Method used for splat arguments: #to_splat
- to_splat is used instead of #to_a.
nil.to_splat returns [].
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]
Also in expressions like
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"] a = [1,2,3] b = [4,5,6] [*a, *b] # => [1, 2, 3, 4, 5, 6]
Mandatory arguments after optional arguments allowed
def m(a, b=nil, *c, d)
[a,b,c,d]
end
m(1,2) # => [1, nil, [], 2]
?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).
- %u behaves like %d for negative values (ruby-core:11575)
Newlines allowed before ternary colon
p 1 == 2 ? 0 : 1 # >> 1
defined? and local variables
RUBY_VERSION # => "1.8.5" RUBY_RELEASE_DATE # => "2006-08-25" a = 0 defined? a # => "local-variable" 1.times do |i| defined? i # => "local-variable(in-block)" end
vs.
RUBY_VERSION # => "1.9.0" RUBY_RELEASE_DATE # => "2007-08-03" a = 0 defined? a # => "local-variable" 1.times do |i| defined? i # => "local-variable" end
Kernel and Object
BasicObject
BasicObject is a top level BlankSlate class:
BasicObject.instance_methods # => ["__send__", "__id__", "==", "send", "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 always call private methods anymore (#__send, #__send!)
ruby-talk:153672 It is still possible to call them with the newly introduced #__send! method.
class Foo; private; def foo; end; end Foo.new.send!(:foo) # => nil Foo.new.send(:foo) # ~> in `BasicObject#send': private method `foo' called for #<Foo:0xa7d3267c> (NoMethodError)
Note that send(meth) (with no explicit receiver) can still call private methods:
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.send(:puts, "foo") # NoMethodError exception
- >> foo
- ~> -:10:in `BasicObject#send': private method `puts' called for 1:Fixnum (NoMethodError)
- ~> from -:10
Kernel#require
The value stored in $" when requiring a file contains the full path, i.e. it works like
$" << File.expand_path(loaded_file)
Object#=~
Now returns nil instead of false.
1 =~ 1 # => nil
Object#tap
Passes the object to the block and returns it (meant to be used for call chaining).
"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?
a = "foo" a.instance_variable_defined? :@a # => false a.instance_variable_set(:@a, 1) a.instance_variable_defined? :@a # => true
Kernel#define_singleton_method
a = ""
a.define_singleton_method(:foo){|x| x + 1}
a.__send!(:foo, 2) # => 3
The new singleton method will be private:
a = ""
a.define_singleton_method(:foo){|x| x + 1}
a.foo(2) # ~> private method `foo' called for "":String (NoMethodError)
Kernel#singleton_methods, Kernel#methods
They now return an array of symbols (instead of strings):
a = "" class << a; def foo; end end a.singleton_methods # => [:foo]
Class and Module
Module#instance_methods, #private_instance_methods, #public_instance_methods
They now return an array of symbols (instead of strings):
class X; def foo; end end X.instance_methods(false) # => [:foo]
vs. (1.8.5)
class X; def foo; end end 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):
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
Module#class_variable_defined?
class X; end X.class_variable_defined? :@@a # => false class X; @@a = 1 end X.class_variable_defined? :@@a # => true
#class_variable_{set,get}
They are public in 1.9, private in 1.8:
class B; self end.class_variable_set(:@@a, "foo") # => "foo"
Module#attr is an alias of attr_reader
Use
attr :foo=
to create a read/write accessor. (RCR#331)
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
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
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
Proc#lambda?
Returns whether the Proc has got "lambda semantics" or "block semantics".
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
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#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_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"] 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]", 1]
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
Enumerable#take
Returns either the first n elements from the enumeration or all elements until the given block returns false (ruby-dev:30407):
a = [1, 2, 3, 4, 5]
a.take(3) # => [1, 2, 3]
a.take {|i| i < 3 } # => [1, 2]
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):
a = [1, 2, 3, 4, 5]
a.drop(3) # => [4, 5]
a.drop {|i| i < 3 } # => [3, 4, 5]
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#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_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"] (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
Therefore
["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:
[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
%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.
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
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#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:
%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
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#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.
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
ary.permutation(n){|c| ...}
Operates like #combination, but with permutations of length n.
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:
[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]]
[1,2].product() # => [[1],[2]]
[1,2].product([]) # => []
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"]
Array#to_s is equivalent to Array#inspect
[1,2,3,4].to_s # => "[1, 2, 3, 4]"
instead of
RUBY_VERSION # => "1.8.5" [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 order!
RUBY_VERSION # => "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]]
vs.
RUBY_VERSION # => "1.8.6"
h={:a=>1, :b=>2, :c=>3, :d=>4} # => {:a=>1, :b=>2, :c=>3, :d=>4}
h[:e]=5
h # => {:e=>5, :a=>1, :b=>2, :c=>3, :d=>4}
h.keys # => [:e, :a, :b, :c, :d]
h.values # => [5, 1, 2, 3, 4]
h.to_a # => [[:e, 5], [:a, 1], [:b, 2], [:c, 3], [:d, 4]]
Hash#to_s is equivalent to Hash#inspect
{1,2,3,4}.to_s # => "{1=>2, 3=>4}"
instead of
RUBY_VERSION # => "1.8.5"
{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?).
"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
h1["a"] # => nil # different objects.
h1[:c] # => "c" # same symbols are all same.
Semantics for Hash#each and Hash#each_pair
- each_pair passes two arguments to the block, #each passes a two-element array
to the block, so
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"]
{1 => 2}.each{|x| p x}
{1 => 2}.each_pair{|x| p x}
# >> [1, 2]
# >> 1
Keep in mind that |x| is equivalent to |x,|.
Hash#select
Returns a hash instead of an association array (ruby-core:11504):
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.8.5", "2006-08-25"]
{'foo'=>'bar','baz'=>'qux'}.select{|k,v| k=='baz' } # => [["baz", "qux"]]
vs.
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"]
{'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?
1.odd? # => true 2.odd? # => false
Integer#pred
The opposite of Integer#succ.
Method
Method#receiver
Returns the receiver of a Method object.
class A; def foo; end end a = A.new a.method(:foo).receiver # => #<A:0xa7c9f6d8>
Method#name
Returns the method name.
Method#owner
Returns the class or module where the method was defined.
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:
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
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
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?.
("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
String
No longer an Enumerable
String is not Enumerable anymore. Use #each_line instead of #each, and #lines (see below) to iterate over the lines.
Encoding-awareness
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
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#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:
"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:
"foo\nbar".lines.sort # => ["bar", "foo\n"]
String#lines accepts an extra argument to indicate the line separator.
If given a block, #lines behaves like #each_line (ruby-core:9218).
String#bytes
Returns an enumerator that will yield each byte in the string:
"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_VERSION # => "1.9.0"
RUBY_RELEASE_DATE # => "2007-02-07"
s = (0..4).to_a.pack("V*")
a = []
s.unpack("V*"){|x| a << x}
a # => [0, 1, 2, 3, 4]
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
"".intern # => :""
However,
:"" # ~> empty symbol literal
Symbol
Symbol#=== matches strings
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.8.5", "2006-08-25"] :a === "a" # => false
vs.
[RUBY_VERSION, RUBY_RELEASE_DATE] # => ["1.9.0", "2007-08-03"] :a === "a" # => true
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 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/"]
Dir.exist?
Equivalent to File.directory?.
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.
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:
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
IO.new(STDOUT).fileno # => 1
StringIO#readpartial
It is an alias for StringIO#sysread.
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#gets, IO#readline, IO#readlines, IO#each_line, IO#lines, IO.foreach, IO.readlines, StringIO#gets, StringIO#readline, StringIO#each, StringIO#readlines
These methods 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
Allows to push back an arbitrarily large character.
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
New format in Time#to_s
Time.new.to_s # => "2006-10-12 10:39:24 +0200"
vs.
RUBY_VERSION # => "1.8.5" Time.new.to_s # => "Thu Oct 12 10:39:27 +0200 2006"
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
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
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
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]
(see ruby-core:10671)
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 # => []
Kernel#getc
Replaced by STDIN.getc.
Object#type
Removed altogether (ruby-core:04335).
"".type # => ERROR: undefined method `type' for "":String
File.exists?
Use File.exist? instead.
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
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:[Differential RSS feeds] [Ruby 1.8.5 in time for the Lantern Festival] [Ruby] [The mechanically verified Ruby 1.9 changelog] [Rails on 1.9: first benchmarks, YARV exposed to non-synthetic tests] [Changes in Ruby 1.9, second update (2006-01)] [Experimental features withdrawn from Ruby 1.9] [Last month, in Ruby 1.9... (2006-03)] [Dissecting matz's monster patch: lots of activity in 1.9 (2006-06)] [Ruby HEAD's been evolving in the last 4 months (2006-10)] [Towards compatibility with Ruby 1.9: Rails, Rake, RubyGems...] [Enhanced xmp code evaluation and annotation] [What's new in Ruby 1.9, Feb. 07 update] [Changes in Ruby 1.9, Oct. 07 update] [First update to the Ruby change summary] [Ruby 1.8.5 released. What's new?]