Hi,
I just updated the list, which is also available in HTML format at
http://www.glue.umd.edu/~billtj/ruby.html.
Regards,
Bill
···
=============================================================================
Things That Newcomers to Ruby Should Know
[1]Plain Text Format
* Resources:
+ HOME PAGE: [2]http://www.ruby-lang.org/en/
+ FAQ: [3]http://www.rubycentral.com/faq/
+ PITFALL:
[4]http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name=pit
fall
+ ONLINE TUTORIAL/DOC/BOOK: [5]http://www.rubycentral.com/book/
+ VERY USEFUL HINTS:
o “Programming Ruby” book by David Thomas and Andrew Hunt,
“When Trouble Strikes” Chapter, "But It Doesn’t Work"
Section
o “The Ruby Way” book by Hal Fulton, Chapter 1: “Ruby In
Review”
1. Use "ruby -w" instead of simply "ruby" to get helpful warnings. If
not invoking "ruby" directly, you can set the environment variable
RUBYOPT to 'w':
+ win32:
C:\> set RUBYOPT=w
or
pressing F5 (to execute) in the Scite editor will give you warnings
(and F4 will position at problematic line).
+ unix:
sh# export RUBYOPT="w"
or
csh# setenv RUBYOPT "w"
2. The notation "Klass#method" in documentation is used only to
represent an "instance method" of an object of class Klass; it is
not a Ruby syntax at all. A "class method" in documentation, on
the other hand, is usually represented as "Klass.method" (which is
a valid Ruby syntax).
3. Be aware of the lexical scoping interaction between local
variables and block local variables. If a local variable is
already defined before the block, then the block will use (and
quite possibly modify) the local variable; in this case the block
does not introduce a new scope. Example:
(0..2).each do |i|
puts "inside block: i = #{i}"
end
puts "outside block: i = #{i}" # >> undefined `i'
On the other hand,
i = 0
(0..2).each do |i|
puts "inside block: i = #{i}"
end
puts "outside block: i = #{i}" # >> 'outside block: i = 2'
and
j = 0
(0..2).each do |i|
j = i
end
puts "outside block: j = #{j}" # >> 'outside block: j = 2'
4. The String#[Fixnum] method does not return the "character" (which
is a string of length one) at the Fixnum position, but instead the
ASCII character code at the position (however, this may change in
the future). Currently, to get the character itself, use
String#[Fixnum,1] instead.
Furthermore, there are additional ASCII conversion methods such as
+ Integer#chr to convert from the ASCII code to the character
65.chr # >> "A"
+ ?char to convert from the character to the ASCII code
?A # >> 65
5. In Ruby, there are two sets of logical operators: [!, &&, ||] and
[not, and, or]. [!, &&, ||]'s precedence is higher than the
assignments (=, %=, ~=, /=, etc.) while [not, and, or]'s
precedence is lower. Also note that while &&'s precedence is
higher than ||'s, the and's precedence is the same as the or's.
6. In the case statement
case obj
when obj_1
....
when obj_k
....
it is the "===" method which is invoked, not the "==" method.
Also, the order is "obj_k === obj" and not "obj === obj_k".
The reason for this order is so that the case statement can
"match" obj in more flexible ways. Three interesting cases are
when obj_k is either a Module/Class, a Regexp, or a Range:
+ The Module/Class class defines the "===" method as a test
whether obj is an instance of the module/class or its
descendants ("obj#kind_of? obj_k").
+ The Regexp class defines the "===" method as a test whether
obj matches the pattern ("obj =~ obj_k").
+ The Range class defines the "===" method as a test whether
obj is an element of the range ("obj_k.include? obj").
7. Array.new(2, Hash.new) # >> [{}, {}]
but the two array elements are identical objects, not independent
hashes. To create an array of (independent) hashes, use the "map"
or "collect" method:
arr = (1..2).map {Hash.new}
Similarly, when creating a hash of arrays, probably the following
is not the original intention:
hsh = Hash.new([])
while line = gets
if line =~ /(\S+)\s+(\S+)/
hsh[$1] << $2
end
end
puts hsh.length # >> 0
One correct and concise way is to write "(hash[key] ||= []) <<
value", such as
hsh = Hash.new
while line = gets
if line =~ /(\S+)\s+(\S+)/
(hsh[$1] ||= []) << $2
end
end
8. Be careful when using "mutable" objects as hash keys. To get the
expected result, call Hash#rehash before accessing the hash
elements. Example:
s = "mutable"
arr = [s]
hsh = { arr => "object" }
s.upcase!
p hsh[arr] # >> nil (maybe not what was expected)
hsh.rehash
p hsh[arr] # >> "object"
9. After reading data from a file and putting them into variables,
the data type is really String. To convert them into numbers, use
the "to_i" or "to_f" methods. If, for example, you use the "+"
operator to add the "numbers" without calling the conversion
methods, you will simply concatenate the strings.
An alternative is to use "scanf"
([6]http://www.rubyhacker.com/code/scanf).
-
It is advisable not to write some white space before the opening
’(’ in a method call; else, Ruby with $VERBOSE set to true may
give you a warning. -
The “dot” for method call is the strongest operator. So for
example, while in some other languages the number after the dot in
a floating point number is optional, it is not in Ruby. For
example, “1.e6” will try to call the method “e6” of the object 1
(which is a Fixnum). You have to write “1.0e6”.
However, notice that although the dot is the strongest operator,
its precedence with respect to method name may be different with
different Ruby versions. At least in Ruby 1.6.7, “puts
(1…3).length” will give you a syntax error; you should write
"puts((1…3).length)" instead. -
In Ruby, only false and nil are considered as false in a Boolean
expression. In particular, 0 (zero), “” or ‘’ (empty string), []
(empty array), and {} (empty hash) are all considered as true. -
Ruby variables hold references to objects and the = operator
copies the references. Also, a self assignment such as a += b is
actually translated to a = a + b. Therefore it may be advisable to
be aware whether in a certain operation you are actually creating
a new object or modifying an existing one. -
There is no standard, built-in deep copy in Ruby. One way to
achieve a similar effect is by serialization/marshalling. Because
in Ruby everything is a reference, be careful when you want to
"copy" objects (such as by using the dup or clone method),
especially for objects that contain other objects (such as arrays
and hashes) and when the containment is more than one level deep. -
Ruby has no pre/post increment/decrement operator. For instance,
x++ or x-- will fail to parse. More importantly, ++x or --x will
do nothing! In fact, they behave as multiple unary prefix
operators: -x == —x == -----x == … -
“0…k” represents a Range object, while “[0…k]” represents an
array with a single element of type Range. For example, if
[0…2].each do |i|
puts "i = #{i}"
end
does not give what you expect, probably you should have written
(0…2).each do |i|
puts "i = #{i}"
end
or
0.upto(2) do |i|
puts "i = #{i}"
end
instead. Note also that Ruby does not have objects of type “Tuple”
(which are immutable arrays) and parentheses are usually put
around a Range object for the purpose of precedence grouping (as
the “dot” is stronger than the “dot dot” in the above example). -
There is some subtle difference between instance variable and
class variable. For instance variables, the order of creation does
not matter: they simply “share” the variable. For example:
class Base
def initialize; @var = ‘base’; end
def base_set_var; @var = ‘base’; end
def base_print_var; puts @var; end
endclass Derived < Base def initialize; @var = 'derived'; super; end def derived_set_var; @var = 'derived'; end def derived_print_var; puts @var; end end d = Derived.new d.base_set_var; d.derived_print_var # >> 'base' d.base_print_var # >> 'base' d.derived_set_var; d.derived_print_var # >> 'derived' d.base_print_var # >> 'derived'
But for class variable, the order of creation does matter. In the
following example, the derived class creates a class variable
first, with the end result of creation of two distinct class
variables:
class Base
def initialize; @@var = ‘base’; end
def base_set_var; @@var = ‘base’; end
def base_print_var; puts @@var; end
endclass Derived < Base def initialize; @@var = 'derived'; super; end def derived_set_var; @@var = 'derived'; end def derived_print_var; puts @@var; end end d = Derived.new d.base_set_var; d.derived_print_var # >> 'derived' d.base_print_var # >> 'base' d.derived_set_var; d.derived_print_var # >> 'derived' d.base_print_var # >> 'base'
For the classes in the inheritance chain to share a single class
variable, the parent has to create the class variable first:
class Base
def initialize; @@var = ‘base’; end
def base_set_var; @@var = ‘base’; end
def base_print_var; puts @@var; end
endclass Derived < Base def initialize; super; @@var = 'derived'; end #changed def derived_set_var; @@var = 'derived'; end def derived_print_var; puts @@var; end end d = Derived.new d.base_set_var; d.derived_print_var # >> 'base' d.base_print_var # >> 'base' d.derived_set_var; d.derived_print_var # >> 'derived' d.base_print_var # >> 'derived'
Things That Are Good to Know
a. In Ruby the "self assignment operator" goes beyond "+=, -=, *=,
/=, %=". In particular, operators such as "||=" also exist (but
currently not for a class variable if it is not yet defined; this
may change in the future). Please see Table 18.4 in the
"Programming Ruby" book for the complete list.
b. For extensive numerical computations, consider "Numerical Ruby"
([7]http://www.ir.isas.ac.jp/~masa/ruby/index-e.html).
c. For (numerical) arrays which consume a large amount of memory and
CPU time, consider "NArray" which is part of the Numerical Ruby
([8]http://www.ir.isas.ac.jp/~masa/ruby/na/SPEC.en).
d. For speeding up some parts of your Ruby code by writing them in C,
consider "Inline"
([9]http://sourceforge.net/projects/rubyinline/).
e. For translation from Ruby to C, consider "rb2c"
([10]http://easter.kuee.kyoto-u.ac.jp/~hiwada/ruby/rb2c/).
f. For integration between Ruby and C/C++, consider "SWIG"
([11]http://www.swig.org/).
g. For integration between Ruby and Java, consider "JRuby"
([12]http://jruby.sourceforge.net/).
h. For integration between Ruby and Lua, consider "Ruby-Lua"
([13]http://ruby-lua.unolotiene.com/ruby-lua.whtm).
i. For creating a stand-alone (Windows) executable, consider "exerb"
([14]http://exerb.sourceforge.jp/index.en.html).
j. For manipulating raw bits, instead of using Fixnum's, consider
"BitVector"
([15]http://www.ce.chalmers.se/~feldt/ruby/extensions/bitvector/).
* For comments on this list, you may e-mail me directly at
[16]billtj@glue.umd.edu.
_________________________________________________________________
Last updated: Oct 16, 2002.
This list itself is available at
[17]http://www.glue.umd.edu/~billtj/ruby.html.
The plain text format is produced from the HTML format with “lynx
-dump”.
_________________________________________________________________
References
- file://localhost/.automount/tulsi/home/tjb/Conf/ruby.txt
- http://www.ruby-lang.org/en/
- http://www.rubycentral.com/faq/
- http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name=pitfall
- http://www.rubycentral.com/book/
- http://www.rubyhacker.com/code/scanf
- http://www.ir.isas.ac.jp/~masa/ruby/index-e.html
- http://www.ir.isas.ac.jp/~masa/ruby/na/SPEC.en
- http://sourceforge.net/projects/rubyinline/
- http://easter.kuee.kyoto-u.ac.jp/~hiwada/ruby/rb2c/
- http://www.swig.org/
- http://jruby.sourceforge.net/
- http://ruby-lua.unolotiene.com/ruby-lua.whtm
- http://exerb.sourceforge.jp/index.en.html
- http://www.ce.chalmers.se/~feldt/ruby/extensions/bitvector/
- mailto:billtj@glue.umd.edu
- http://www.glue.umd.edu/~billtj/ruby.html