This is a repost. The original from August 2nd started getting comment spam, and I accidentally deleted the post while deleting the spammy comments. The original, valid comments are gone as well, which is unfortunate, because Tom Klaasen and Dmitry Kim made helpful points that resulted in corrections to the post below.
Someone recently emailed the ruby-core mailing list asking "Is there some list of 'bullet points' on the major differences between the syntax of Ruby 1.8 and Ruby 1.9 available somewhere?" The response, of course was a link to the definitive list of changes in Ruby 1.9.
But that is an exhaustive list instead of just highlighting the major changes. So, the following is my somewhat more digested list of the important changes, as I understand them. Additions, corrections, clarifications, and so forth are welcome in the comments.
Text
- Characters are represented by single-character strings,
rather than integers:
?Areturns"A"instead of 65- "HELLO"[1] returns "E" instead of 69.
s[x]is now the same ass[x,1] - Use
ordmethod of String to get character encoding. It returns the encoding of the first character of the string
- Strings are no longer
Enumerable, and theeachmethod has been removed. Useeach_lineandeach_byteto iterate lines and bytes. Both of these methods can return enumerators (see below), which areEnumerable. - Ruby 1.9 adopts the Oniguruma regexp engine, which adds advanced new features for regular expression wizards.
-
Additional changes are expected to Ruby's Unicode and
multi-byte string support, but Matz has not unveiled them
yet. Strings may have an
encodingmethod for querying or setting their encoding.
Ranges
-
member?andinclude?work differently if the endpoints of a range are not numbers: they actually iterate withsuccto test membership in that case. - The new method
covers?does whatmember?andinclude?did in 1.8
Hashes
-
New hash syntax. When the keys of a hash are symbols, you
can move the colon from the beginning of the symbol to the
end (no space allowed) and omit the
=>. So this hash{:a=>1,:b=>2}turns into{a:1,b:2}. The Ruby 1.8 syntax is still supported, of course.
Parallel Assignment
- Any number of splat operators may appear on the right-hand side of a parallel assignment in Ruby 1.9. Previously only the last rvalue could have a splat.
- The left-hand side of a parallel assignment may have only one splat operator, as always, but it is no longer required to be on the last lvalue. In Ruby 1.9 a splat may appear before any one lvalue.
-
Remember that the rules of parallel assignment apply to
block invocation as well: the arguments to
yieldare rvalues, and the block parameters are lvalues. So these splat changes apply to blocks as well. -
In Ruby 1.8, the value of a parallel assignment expression
was an array of the lvalues. For efficiency, Ruby 1.9
evaluates all parallel assignments to
true.
Enumerators
-
The iterator methods of core classes and modules like
String,Fixnum,Array,HashandEnumerablenow return an enumerator object when invoked with no block. An enumerator is anEnumerableobject. The enumerator return by each of these iterator methods uses that underlying iterator in place of theeachmethod normally used by theEnumerablemixin. So we can write things like:counter = (1..10).each # returns an enumerator counter.each_with_index { |n,i| puts n,i } -
Ruby makes
Enumerable::Enumeratorcore, so you no longer have to require "enumerator" to get methods likeenum_for
Blocks
- Block parameters are always local to their blocks, even when the enclosing scope includes a variable by the same name. Use -w to get a warning when this will change the behavior of your code.
- Block parameters must be local variables in Ruby 1.9. No more assigning to instance variables or global variables as a side-effect of block invocation
-
You can declare block-local variables in Ruby 1.9. Just
follow the ordinary list of block parameters with a
semi-colon and follow it with a comma-separated list of
variable names:
With this block declaration,hash.each { |k,v; x,y,z| ... }x,y, andzwill be local to the block, even if they are already defined in the enclosing scope. - As per the parallel-assignment changes described above a block parameter list may a splat operator before any one parameter. It is no longer required to be the last one.
- The last block parameter may be prefixed with an ampersand to make it receive a block, just as you can do with methods. This is typically only useful when the block is being turned into a proc or lambda
Procs and Lambdas
-
Kernel.procis now a synonym forProc.new:procnow creates a proc andlambdacreates a lambda. (Both procs and lambdas are still instances ofProc, of course.) -
The
Symbol.to_procmethod is now built-in to Ruby. -
Ruby 1.9 supports a (strange at first) new syntax for
defining lambdas:
->(x,y) { x + y } # same as lambda {|x,y| x + y}-
Parentheses are optional in this new syntax:
->x,y { x + y } # same as lambda {|x,y| x + y} - The new lambda syntax supports block-local variable declarations following a semicolon just as the regular block syntax does.
-
The new lambda syntax allows argument defaults using the
same syntax as method declarations:
sale_price = ->(price,discount=.25) { (1.0-discount)*price }
-
Parentheses are optional in this new syntax:
-
Procs and lambdas can be invoked with parentheses preceded
by a period. Given a lambda
sum, the following three lines are synonyms:sum.call(1,2) sum[1,2] sum.(1,2) -
Procs now have a
yieldmethod that is an alternative tocall.yielduses yield semantics rather than method calling semantics to invoke the proc. This means that it is more relaxed about arity mis-matches and behaves like parallel assignment when the argument is a single array.
Bindings
-
Bindingobjects have anevalmethod to evaluate in that binding. This is an alternative to passing the binding as the second argument toKernel.eval. -
Proc.bindingis now a private method. It is not clear if this is a bug or if that method will no longer be available.
Continuations
Continuations are not supported in Ruby 1.9
Private Methods
- The method name resolution algorithm has changed or may be changing to alter the way private methods are looked up. The details are still unclear (to me, at least).
Class Variables
- Class variables are no longer shared by a class and its subclasses. A subclass can read the values of class variables defined by its superclass. But if it sets the value of such a variable, it simply creates its own local copy of the variable, and no longer alters the value seen by the superclass.
Math
-
Math.log2computes base-2 log - Math.log(x,y) computes the log base-y of x



