# Things That Newcomers to Ruby Should Know

### Table of Contents

- Resources

1. Using warnings
2. Interactive shell
3. On-screen documentation
4. Class#method notation
5. Getting characters from a String
6. Array and Hash default values
7. Mutable Hash keys
8. Reading numerals from a file
9. Pre/Post Increment/Decrement Operators
10. Lexical scoping in blocks
11. Two sets of logical operators
12. The === operator and case statements
13. White space
14. The "dot" method call operator
15. Range objects
16. Boolean values
17. Variables, references, and objects
18. Deep copy
19. Class variables
20. Substituting Backslashes

- Things That Are Good to Know :-)

- Resources:
  - `HOME PAGE`: http://www.ruby-lang.org/en/
  - `FAQ`: http://www.rubycentral.com/faq/ (original) or http://www.rubygarden.org/iowa/faqtotum (latest)
  - `PITFALL`: http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name=pitfall
  - `ONLINE TUTORIAL/DOC/BOOK`: http://www.rubycentral.com/book/
  - `VERY USEFUL HINTS`:
    - "Programming Ruby" book by David Thomas and Andrew Hunt, "When Trouble Strikes" Chapter, "But It Doesn't Work" Section
    - "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. Ruby has an interactive shell; try to invoke the command "`irb`" instead of "`ruby`". "irb" is best used for experimenting with the language and classes; you may try things out in this environment before putting them in your programs.

3. For convenient on-screen Ruby documentation, consider to use (and install, if necessary) "ri" (http://www.pragmaticprogrammer.com/ruby/downloads/ri.html).
   For example, too see the methods of the `File` class, run "`ri File`". To read about its `open` method, type "`ri File.open`".

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

5. 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"

   - `?chr` to convert from the character to the ASCII code

                     ?A        # -> 65

   Using these properties, for example, some ways to get the last character in a string is by writing "`aString[-1, 1]`" or "`aString[-1].chr`".

6. `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

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

8. 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" (http://www.rubyhacker.com/code/scanf).

9. 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 == .....`. To increment a number, simply write `x += 1`.
   (An explanation for this language design by the author of Ruby can be found at http://www.ruby-talk.org/2710.)

10. Beware 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'

11. 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. An example:

                    a = 'test'
                    b = nil
                    both = a && b       # both == nil
                    both = a and b      # both == 'test'
                    both = (a and b)    # both == nil

    (The reason for this language design and some more examples can be found at http://www.rubygarden.org/iowa/faqtotum/abN18mrYFE49E/c/1.13.3.3.5.)

12. 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`").

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

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

15. "`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. Notice 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).

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

17. 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.
    For example, `string << "another"` is faster than `string += "another"` (no extra object creation), so you would be better off using any class-defined update-method (if that is really your intention), if it exists. However, notice also the "side effects" on all other variables that refer to the same object:

                    a = 'aString'
                    c = a
                    a += ' modified using +='
                    puts c    # -> "aString"

                    a = 'aString'
                    c = a
                    a << ' modified using <<'
                    puts c    # -> "aString modified using <<"

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

19. A class variable is in general per-hierarchy, not per-class (i.e., a class variable is "shared" by a parent and all of its descendants, in addition to being shared by all instances of that class). One subtle exception is if a child class creates a class variable before its parent does. For example, when a parent creates a class variable first:

                    class Base
                      def initialize;     @@var = 'base'; end
                      def base_set_var;   @@var = 'base'; end
                      def base_print_var; puts @@var;     end
                    end

                    class Derived < Base
                      def initialize;        super; @@var = 'derived'; end # notice
                      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'

    In the above code, the class variable `@@var` is indeed "shared" by the `Base` and `Derived` classes. However, now see what happens when a child class creates the variable first:

                    class Base
                      def initialize;     @@var = 'base'; end
                      def base_set_var;   @@var = 'base'; end
                      def base_print_var; puts @@var;     end
                    end

                    class Derived < Base
                      def initialize;        @@var = 'derived'; super; 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    # -> 'derived'
                                       d.base_print_var       # -> 'base'
                    d.derived_set_var; d.derived_print_var    # -> 'derived'
                                       d.base_print_var       # -> 'base'

    In this case, the parent and child classes have two independent class variables with identical names.

20. Substituting backslashes may be tricky. Example:

                    str = 'a\b\c'                     # -> a\b\c
                    puts str.gsub(/\\/,'\\\\')        # -> a\b\c
                    puts str.gsub(/\\/,'\\\\\\')      # -> a\\b\\c
                    puts str.gsub(/\\/,'\\\\\\\\')    # -> a\\b\\c
                    puts str.gsub(/\\/) { '\\\\' }    # -> a\\b\\c
                    puts str.gsub(/\\/, '\&\&')       # -> a\\b\\c

## Things That Are Good to Know :-)

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

2. For a "cookbook" with many algorithm and code examples, consider "PLEAC-Ruby" (http://pleac.sourceforge.net/pleac_ruby/t1.html).

3. For extensive numerical computations, consider "Numerical Ruby" (http://www.ir.isas.ac.jp/~masa/ruby/index-e.html).

4. For (numerical) arrays which consume a large amount of memory and/or CPU time, consider "NArray" which is part of the Numerical Ruby (http://www.ir.isas.ac.jp/~masa/ruby/na/SPEC.en).

5. For speeding up some parts of your Ruby code by writing them in C, consider "Inline" (http://sourceforge.net/projects/rubyinline/).

6. For Ruby to C translation, consider "rb2c" (http://easter.kuee.kyoto-u.ac.jp/~hiwada/ruby/rb2c/).

7. For Ruby and C/C++ integration, consider "SWIG" (http://www.swig.org/).

8. For Ruby and Java integration, consider "JRuby" (http://jruby.sourceforge.net/).

9. For Ruby and Delphi integration, consider "Apollo" (http://www.users.yun.co.jp/~moriq/apollo/index-en.html).

10. For embedding Python in Ruby, consider "Ruby/Python" (http://www.ruby-lang.org/en/raa-list.rhtml?name=Ruby%2FPython).

11. For embedding Lua in Ruby, consider "Ruby-Lua" (http://ruby-lua.unolotiene.com/ruby-lua.whtm).

12. For creating a stand-alone (Windows) executable, consider "exerb" (http://exerb.sourceforge.jp/index.en.html).

13. For manipulating raw bits, instead of using Fixnums, consider "BitVector" (http://www.ce.chalmers.se/~feldt/ruby/extensions/bitvector/).

- For comments on this list, you may e-mail me directly at billtj@glue.umd.edu.

Last updated: Nov 25, 2002.
This list itself is available at http://www.glue.umd.edu/~billtj/ruby.html.
The plain text format is produced from the HTML format with "`lynx -dump -nolist`" (and some minor editing).