The Ruby Programming Language
Lecture Notes for CS 142
Fall 2010
John Ousterhout
- Readings for this topic:
- Read Chapter 1 of The Ruby Programming Language, then
skim Chapters 2-7 to get a feel for the operators, statements,
and class facilities. You can read more of the details as you
are working on the projects.
- Read Sections 8.9 and 8.10 of The Ruby Programming Language.
You will need this information for Project #2.
- Ruby basics:
- Scripting language (more dynamic, interpreted than Java)
- Very dynamic, flexible: metaprogramming facilities
(write programs that write programs)
- Pure object oriented: absolutely everything is an object
- Large language, many features
- Simple code example:
sum = 0
i = 1
while i <= 10 do
sum += i*i
i = i + 1
end
puts "Sum of squares is #{sum}\n"
- Syntactic differences from Java and C:
- No variable declarations
- Newline terminates statements (semicolons OK too)
- do...end instead of {...}.
- Optional parentheses in method invocation
- Built-in datatypes:
- Numbers:
- Integer (Fixnum and Bignum)
- Float
- Complex
- BigDecimal
- Rational
- Strings:
- Single quotes (only a few backslash sequences)
- Double quotes (lots of backslash sequences)
- %q (like ''), %Q (like ""):
s1 = %q(String contains quotes: '"')
s2 = %Q|More quotes ("") and subs: #{x}|
- Here documents:
doc = <<END
First line
Second line
END
- Symbols:
- Notation: :foo
- A string constant, more efficient in many situations
- Typically used for unique identifiers such as variable and
method names, hash keys, etc.
- true, false, nil
- Arrays:
x = Array.new
y = ["Alice", 23, 7.3]
- -1 index refers to last element
- Hashes:
x = Hash.new
y = {"item" => "Corn Flakes", "weight" => 18}
y = {:item => "Corn Flakes", :weight => 18}
- Range: [1..20]
- Variables:
- Untyped: types associated with values, not variables
- Any variable can hold any value
- No declarations: variables created on first assignment
- Variable scope determined syntactically:
- $foo: global variable
- @foo: instance variable in an object
- @@foo: class variable
- MAX_USERS: constant (by convention)
- Anything else is a local variable
- Operators and expressions: fairly similar to Java.
- Statements:
if x < 10 then
...
elsif x < 20
...
else
...
end
while x < 10 do
...
end
array = [14, 22, 34, 46, 92]
for value in array do
...
end
- Methods:
- Factorial example:
def fac(x)
if x <= 0 then
return 1
end
return x*fac(x-1)
end
- Every method is associated with a class (default: private method
of Object class).
- Methods always return values:
- Result of last expression
- Default: nil.
- Optional parentheses in method invocation (can be confusing)
puts "Hello world"
f (3+2)+1
- Default values for arguments:
def inc(value, amount=1)
value+amount
end
- Variable-length argument lists:
def max(first, *rest)
max = first
for x in rest do
if (x > max) then
max = x
end
end
return max
end
- Name-value arguments: use a hash.
- Can omit curly braces to supply value for last argument:
def create_widget(size, properties)
...
end
create_widget(6, {:id => "table22", :class => "Cart"})
create_widget(6, :id => "table22", :class => "Cart")
- Iterators, blocks, and yield:
- Ruby makes it possible to define new control structures
called iterators.
- Example:
oddNumbers(3) do |i|
print(i, "\n")
end
def oddNumbers(count)
number = 1
while count > 0 do
yield(number)
number += 2
count -= 1
end
end
- do ... end is a block: a chunk of code passed to
the oddNumbers method.
- Blocks usually have arguments: i
- yield invokes the block passed to the method, passing
it arguments.
- A block is a closure: it has access to all variables visible at
the point of its declaration
- Any method can be passed a block.
- for loops are actually implemented as an iterator; the
following 2 loops have identical behavior:
array = [14, 22, 34, 46, 92]
for value in array do
print(value, "\n")
end
array.each do |value|
print(value, "\n")
end
- each is a method implemented by the Array class; it
iterates over the elements of its array.
- Can use for on any object that supplies an each method.
- Classes:
- Example:
class Point
def initialize(x, y)
@x = x
@y = y
end
def x
@x
end
def x=(value)
@x = value
end
end
p = Point.new(3,4)
p.x => 3
p.x = 44;
- initialize method called during object construction
- No direct access to instance variables: instead, define methods
foo and foo=.
- Methods can be public, protected, or private.
- Inheritance: class Child < Parent
- Duck typing:
- No type-based restrictions on invoking methods
- Can invoke a method foo on any object for which a
foo method is defined.
- Module: a group of methods that can be shared by many classes;
- Similar to multiple inheritance or mixins.
- Like the implementation of a Java interface.
- Example: Enumerable
- Your class implements each method.
- Mix in the Enumerable module to get many additional methods.
class MyClass
include Enumerable
...
def each
...
end
end
- Example Enumerable methods:
- sort
- map: create a new collection by applying a block to
each element
- select: create a new collection of elements that
meet certain criteria
- min, max
- Metaprogramming: programs that help you write programs
- Reflection: like Java, can examine the state
and structure of a Ruby program while it is running.
- eval: can create new programs on-the-fly and execute them.
- Can define new classes, methods, and modules on-the-fly.
- The following code automatically defines accessor methods
for x and y:
Class definition is not compiled, it's executed.
- method_missing: can catch invocations of undefined methods:
- Define new methods "just-in-time" when referenced.
- Simulate the existence of a large variety of methods.
- And much more... facilities for domain specific languages, etc.