eigenclass logo
MAIN  Index  Search  Changes  PageRank  Login

Changes in Ruby 1.9

Last major update on 2007-08-03

I have scanned over 35000 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



New syntax and semantics

New constant lookup rules

Now constants are looked up in the following order:

  1. current class
  2. super classes except Object
  3. lexically enclosing classes/modules
  4. 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

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)... 
  1. ~> -: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)}

ruby-dev:23533

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

  1. 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

(ruby-dev:29014)

   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

ruby-dev:29189

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__", "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 always call private methods anymore (#__send, #__send!, #funcall)

ruby-talk:153672 It is still possible to call them with the newly introduced #__send! and funcall methods.

class Foo; private; def foo; end; end
Foo.new.funcall(: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
  1. >> foo
  2. ~> -:10:in `BasicObject#send': private method `puts' called for 1:Fixnum (NoMethodError)
  3. ~> 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)

ruby-dev:26079

Object#=~

Now returns nil instead of false.

 1 =~ 1		# => nil

ruby-core:05391.

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

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

Binding#eval

RCR 251, accepted.


a = 1
binding.eval("a")		# => 1

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. ~> -: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#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 true (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

ruby-dev:26895

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]

ruby-talk:147728

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"

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

Enumerable#minmax and minmax_by

Returns both the minimun and the maximum at once as a two-element array.

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

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"]

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"

Hash

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

  1. 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"}

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

(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)

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

(ruby-talk:167420)

Regexp

Regexp#=== matches symbols

This allows you to do things like

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

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.

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.

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.

  1. 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#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).

Zero-length symbols allowed

"".intern                                         # => :""

However,

:""                                               # ~>  empty symbol literal

Struct

Struct#inspect

Does not show the class name for anonymous structs:

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

vs. (1.8.5)

Struct.new(:a).new("")                            # => #<struct #<Class:0xa7d6ccf0> a="">

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

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

File.open("/tmp/[", "w"){|f| f.puts "hi"}
Dir["/tmp/["]		# => []
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.

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"

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).

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).

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

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]

(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		# => []

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

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