class Foo
attr_accessor :bar
def test
[1,2,3].each {|@bar| }
# @bar will be 3 here
end
end
This no longer works in ruby1.9, you as it always creates a new local variable block argument. The equivalent in ruby1.9:
class Foo
attr_accessor :bar
def test
[1,2,3].each {|bar| @bar=bar }
# @bar will be 3 here
end
end
i = 0 [1,2,3].each {|i| } puts i
This will print 0
in ruby1.9, as the variables named i
inside/outside the block are different, and 3
inruby1.8, as here the block reuses the outside variable i
.
As with most warning, this warning doesn’t means that your code is incorrect, only that it might be incorrect.
For example the code bellow works the same in ruby1.9 and 1.8:
options = options.inject({}) do |options,pair| options[pair.first.to_sym] = pair.last.to_sym; options end
It still makes sense to rewrite the above code just to supress warnings.
Note: You should set RUBYOPT
to -w
, or start your program with ruby -w
, for this warning to show up
,
in hash definition, in 1.9 you have to use =>
. So the following valid ruby1.8:
{"a","b"}
has to be rewritten in ruby1.9:
{"a" => "b"}
US-ASCII
, if you have a non ASCII character in your text file you have to specify the encoding of the source code. You can do it by adding the following line to yourruby file:# coding:utf-8
to_a
method, so in ruby1.8 you can write:lines = string.to_a
The equivalent in ruby1.9 is:
lines = string.lines.to_a # chars = string.chars.to_a # to get array of chars # bytes = string.bytes.to_a # to get array of bytes
The issue with this solution, is that the ruby1.9 solution is not compatible with ruby1.8.
Some ideas for a ruby1.9 and ruby1.8 compatible solution:
The first one is to add a lines
method to the String
, so you can use the ruby1.9 syntax:
unless String.method_defined?(:lines) then
class String
def lines
to_a
end
end
endif
The downside is that this lines
method is not 100% compatible with ruby1.9 String#lines – for example string.lines(”/n/r”) won’t work.
The second one is to check at each call whether it has the lines
method:
if str.respond_to?(:lines) then
lines = string.lines.to_a
else
lines = string.to_a
end
case
or if
with :
instead of then
Ruby1.8 allows the use of : shortcut instead of then in if
and case
expressions. In Ruby1.9 this is no more allowed.
case 'test'
when 'test': print 'OK'
end
In ruby1.9 you’ll get a syntax error, so you have to replace the ‘:’ with ‘then’
case 'test' when 'test' then print 'OK' end
require "base64"
: ruby 1.9 ships without base64. You should use Array#pack, unpackrequire 'base64' enc = Base64.encode64('Send reinforcements') plain = Base64.decode64(enc)
In ruby1.9 you can write:
enc = ['Send reinforcements'].pack( 'm' ) plain = enc.unpack( 'm' )[0]
RSTRING_LEN
, RSTRING_PTR
macros instead of directly accessing the len
, ptr
members.len = RSTRING(foo)->len ptr = RSTRING(foo)->ptr
Should be changed to
len = RSTRING_LEN(foo); ptr = RSTRING_PTR(foo);
Object.methods.include?("to_s")
The ruby1.9 version is:
Object.methods.include?(:to_s)
And the following works in ruby1.8 and 1.9:
object.respond_to?(:some_method)
nil
.delete
method instead:ENV.delete('MY_ENV_VARIABLE')
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.
?A
returns "A"
instead of 65s[x]
is now the same as s[x,1]
ord
method of String to get character encoding. It returns the encoding of the first character of the stringEnumerable
, and the each
method has been removed. Use each_line
andeach_byte
to iterate lines and bytes. Both of these methods can return enumerators (see below), whichare Enumerable
.encoding
method for querying or setting their encoding.member?
and include?
work differently if the endpoints of a range are not numbers: they actually iterate with succ
to test membership in that case.covers?
does what member?
and include?
did in 1.8=>
. So this hash {:a=>1,:b=>2}
turns into{a:1,b:2}
. The Ruby 1.8 syntax is still supported, of course.yield
are rvalues, and the block parameters are lvalues. So these splat changes apply to blocks as well.true
.String
, Fixnum
, Array
, Hash
and Enumerable
now return an enumerator object when invoked with no block. An enumerator is an Enumerable
object. The enumerator return by each of these iterator methods uses that underlying iterator in place of the each
method normally used by the Enumerable
mixin. So we can write things like:
counter = (1..10).each # returns an enumerator
counter.each_with_index { |n,i| puts n,i }
Enumerable::Enumerator
core, so you no longer have to require "enumerator" to get methods like enum_for
hash.each { |k,v; x,y,z| ... }
With this block declaration, x
, y
, and z
will be local to the block, even if they are already defined in the enclosing scope.Kernel.proc
is now a synonym for Proc.new
: proc
now creates a proc and lambda
creates a lambda. (Both procs and lambdas are still instances of Proc
, of course.)Symbol.to_proc
method is now built-in to Ruby.
->(x,y) { x + y } # same as lambda {|x,y| x + y}
->x,y { x + y } # same as lambda {|x,y| x + y}
sale_price = ->(price,discount=.25) { (1.0-discount)*price }
sum
, the following three lines are synonyms:
sum.call(1,2)
sum[1,2]
sum.(1,2)
yield
method that is an alternative to call
. yield
uses 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.Binding
objects have an eval
method to evaluate in that binding. This is an alternative to passing the binding as the second argument to Kernel.eval
.Proc.binding
is now a private method. It is not clear if this is a bug or if that method will no longer be available.Math.log2
computes base-2 log