Ruby this 26-Jul-16

advertisement
Ruby
(Bet you can’t do this in Java!)
26-Jul-16
“Hello World” in Ruby

puts "Hello World!"
Euclid’s algorithm



def euclid x, y
while x != y
if x > y then x -= y end
if y > x then y -= x end
end
x
end
puts "Enter two numbers: "
STDOUT.flush
x = Integer(gets)
y = Integer(gets)
puts "The GCD of #{x} and #{y} is #{euclid x, y}“
Enter two numbers:
24
108
The GCD of 24 and 108 is 12
General principles




Everything is dynamic and may be changed
All values are objects (there are no “primitives”)
Variables are typeless and need not be declared
Ruby avoids unnecessary punctuation

A statement on a line by itself needs no semicolon





Multiple statements on a line are separated by semicolons
A line is continued if it ends in an operator, comma, or backslash
Parameters to a method don’t usually need parentheses
Conditions (in if, while, etc.) usually don’t need parentheses
Correct capitalization is required, not optional


Convention: Multiword variables use underscores, not camelCase
Convention: Standard indentation is two spaces
Numbers

Numbers may be written in decimal, hexadecimal, octal, or
binary






Numbers larger than four bytes are automatically treated as
Bignum objects
For readability, numbers may contain (but not begin or end with)
underscores


Decimal: 3405691582
Hex: 0xCAFEBABE or 0XCAFEBABE
Octal: 031277535276 or 0o31277535276
Binary: 0b11001010111111101011101010111110 or 0Betc.
Examples: 3_405_691_582, 0b_111_101_101
Integers may be indexed to retrieve their bits

Example: 5.step(0, -1) { |i| print 6[i] }  000110
Other data types

Strings can be singly quoted or doubly quoted
Doubly quoted strings can interpolate values for #{expression} and for
#@variable, and allow the usual escape characters
 In a singly quoted string, \' is the only recognized escape character
 Strings are not immutable
Arrays are untyped and expandable, for example [1, 2, "hi"]
Ruby has hashes: { :banana  'yellow', :cherry => 'red' }






Ruby has regular expressions, dates, and times
Ruby has ranges, such as 1..10
Ruby has symbols, which stand for themselves




You can think of them as immutable strings
Examples are :banana and :cherry
Since they are immutable, they make good keys for hashes
They are also often used to refer to methods and variables: attr :do_it
Operators





Almost all the Java operators, except ++ and -Ruby uses :: to mean the same as . in Java
Ruby uses =~ and !~ for Perl-style regular expressions
** is the exponentiation operator
+ is used to concatenate strings


.. is an inclusive range, ... is an exclusive range




There is a to_s method for converting other things to strings
So 1..4 and 1...5 both mean 1, 2, 3, 4
0..k is a range object, but [0..k] is an array with one element, a range
defined? is a prefix operator that returns a true value or nil
Ruby has both !, &&, || and also not, and, or

Precedence is ! > && > ||, but not > and == or
Assignment and alias statements

Assignment statements use =, +=, *=, etc.



You can have multiple assignment: x, y = y, x swaps the
values of x and y
Ruby does not have the ++ and -- operators
You can create a new name for a method, operator,
global variable, or regular expression backreference


Syntax: alias new_name original_name
Example: alias display puts
if statements

Multi-line version:



if condition then
code
elsif condition then
code
else
code
end
The “then” is optional at the end of a line
Single-line versions:


if condition then code elsif condition then code else code end
 “then” is required to separate condition from code
statement if condition
unless statements


“unless” means “if not”
Multi-line version:



unless condition then
code
else
code
end
The “then” is optional at the end of a line
Single-line versions:


unless condition then code else code end
 “then” is required to separate condition from code
statement unless condition
case and ===



case expr_1
when expr_2 then
code
when expr_3, ..., expr_n then
code
else
code
end
Cases do not fall through; no
break is needed
Comparisons use
expr_n === expr_1
and not the other way around

expr_n === expr_1 has many
meanings





Simple equality test
expr_1 =~ expr_n
expr_n.kindof? expr_1
expr_n.include? expr_1
The === operator has the
misleading name “case
equality operator”
Loops in Ruby

Ruby has several loops





for variable in range do
statements
end
while condition do
statements
end

begin
statements
end while condition

statement while condition

statement until condition

loop { statements }
until condition
statements
end
begin
statements
end until condition


loop do
statements
end
However, loops are not used as often in
Ruby as in other languages
Instead, Ruby programmers use iterator
methods
Loop controls






break gets you out of loops
Within a loop, next jumps to just before the loop test
Within a block, next exits the block with nil
retry restarts the loop body after reevaluating the
condition or getting the next iterated element
Within a loop, redo restarts the loop body, but does not
reevaluate the condition or get the next iterated element
Within a block, redo restarts the yield or call
Exceptions






raise message raises a RuntimeError
raise exception raises an error of the given type
raise exception, message
rescue
rescue ExceptionType, ..., ExceptionType
rescue ExceptionType, ..., ExceptionType =>
variable


Catches exceptions within a method, or within a begin...end
block, or can be used as a statement suffix
Example on next slide
Blocks

A block is a set of statements enclosed by begin..end, by do..end, or by {..}





begin introduces a new scope; variables seen for the first time inside a begin..end
block are local to that scope
do..end and {..} are interchangeable
Any block or method can include rescue or rescue/ensure
begin...rescue...ensure...end is like Java’s try...catch...finally
Example:

begin
code
rescue exception
code
ensure
code
end
Defining methods

Defining an instance method:


Defining a class method:






def method_name(parameter1, ..., parameterN)
statements
end
def Class_name.method_name(parameter1, ..., parameterN)
statements
end
Parentheses are optional
A method may contain explicit return and/or return value statements
A method may return multiple values: return x, 2*x, x**2
A method which reaches the end returns the value of the last statement
executed (often nil)
A method may also have a block as an (invisible) parameter

The block is not mentioned in the def line, but is executed when the method
evaluates the yield statement
Defining classes

class Employee < Person # ‘<‘ means “extends”
@@number = 0
# class variable
attr_reader :name
# creates a getter for @name
def initialize(name)
@name = name
@@number += 1
end
end

# this is the constructor
secretary = Employee.new("William")
Calling methods

Methods may be called as in Java


Parentheses are usually unnecessary


puts "x = #{x}"
All values are objects, and may have methods



puts("x = #{x}")
x = y.abs
n = "abcdefg".length
A method may be passed a block as an “invisible” parameter



def twice n
yield 2 * n # uses the block
99
end
p = twice(7) { |y| puts "y = #{y}" }
puts "p = #{p}"
y = 14
p = 99
Iterators



An iterator returns values one at a time
The syntax is
object.iterator { |value| statement }
or
object.iterator do |value|
statements
end
The object is typically an array, a range, or a hash, but it
can be any object with a coroutine
Iterators







In Ruby, loops are considered low-level, to be used only
when there is no appropriate iterator
collection.each – step through every element
n.times – do a block n times
n.downto(limit) – step from n down to and including
limit
n.upto(limit) – step from n up to and including limit
string.each_line – get each line from a string
string.each_char – get each character (as an integer)
from a string
Example use of an iterator


a = [1, 1, 2, 3, 5, 8, 13]
a.each { |i| print " #{i}" }


a.each do |i|
print " #{i}"
end




Output: 1 1 2 3 5 8 13
Output: 1 1 2 3 5 8 13
In the above, each is a method
A block is a chunk of code enclosed by {...} or by do...end
By convention, braces are used for single-line blocks, do...end
for multi-line blocks
String#each_char

In a previous slide, I had:


string.each_char – get each character (as an integer) from
a string
This method is described in the documentation, but
doesn't seem to exist



There is a method String#each_byte, however, that does
what the above description says each_char does
If we really want to get each character, we can do that
class String
def each_char
each_byte { |b| yield b.chr }
end
end
Blocks again

A block is a chunk of code that can be passed as a
parameter to a method


A block isn’t a statement—it can’t be used alone
It’s passed as an “invisible” parameter, and executed with
the yield statement
Simplest use of yield


def three_times
puts "---------- three_times“
yield
yield
yield
end
three_times { puts "hello" }

---------- three_times
hello
hello
hello
My version of loop


def my_loop
yield while true
end
a = [1, 2, 3, 5, 8, 13, "hi"]
my_loop do
break if a.empty?
print a.pop
end
puts "Done"

hi1385321Done
Fibonacci numbers


def fibonacci_upto n
i1, i2 = 1, 1
while i1 < n
yield i1
i1, i2 = i2, i1 + i2
end
end
fibonacci_upto(100) { |f| print " ", f }

1 1 2 3 5 8 13 21 34 55 89
Passing a parameter to the block


def count_to n
puts "---------- count_to #{n}"
for i in 1..n
yield
end
end
count_to 3 { puts "hello" }

---------- count_to 3
hello
hello
hello
Returning a value from a coroutine


def count_to_3
puts "---------- count_to_3"
yield 1
yield 2
yield 3
end
count_to_3 { |result| puts result }

---------- count_to_3
1
2
3
Regular expressions


Ruby has regular expressions, almost identical to the
way they are done in Perl
Example:


hamlet = "The slings and arrows of outrageous fortune."
hamlet.scan(/w+/)
["The", "slings", "and", "arrows", "of", "outrageous",
"fortune"]
Arrays

An array literal can be written with brackets and commas



a = [1, 1, 2, 3, 5, 8, 13, "hi"]
Arrays are zero based: a[2] == 2
Arrays can be expanded

a = a + [21, 34]
pa




[1, 2, 3, 5, 8, 13, "hi", 21, 34]
Arrays can be treated as stacks, with a.push(v) and v = a.pop
The join(string) method creates a string of the elements of the
array, with the given string between each pair of elements
You can take slices of arrays, sort them, find unique elements,
perform set operations, transpose 2-dimensional arrays, etc.

Before you write methods to manipulate arrays, you should look to see
whether the method you want has already been written
Hashes

A hash (hash table) literal can be written with braces,
commas, and the => arrow


h = {:apple => :red, :banana => :yellow,
:cherry => :red}
Element access is similar to that for arrays:

h[:banana]


h[:apple] = :green
ph


:yellow
{:banana=>:yellow, :cherry=>:red, :apple=>:green}
You can use any types for keys and values, but the
characteristics of symbols make them especially useful
as keys
Adding and removing methods

def adds a method; undef removes a method


To add an instance method, first “open” the class


Example: class String; def nchars; length; end; end
There are several ways to add a class method to a class



The only parameter to undef is the method name
def Person.species; 'human'; end
Within the Person class, you can use def self.species
You can add a method to individual objects

def oscar.mood; 'grouchy' ; end
Attributes (instance variables)



Attributes (instance variables) of an object are written with an @
prefix: @name, @age, @hobbies, @favorite_language
By default, attributes are private
You can write getters:


def name
@name
end
You can write setters:



def name=(new_name)
@name = new_name
end
When you define the setter, there is no space before the = in the header
When you call the setter, you can use a space: teacher.name = "Dave"
 Yes, we are calling the method name= !
Shorthand for getters and setters

Writing code for routine getters and setters is tedious, so in Ruby
we don’t have to do it

Shorthand for creating getters:
attr_reader :name, :age, :hobbies





Note the use of symbols, not variables or strings
Shorthand for creating setters:
attr_writer :name, :hobbies
Shorthand for creating both at once:
attr_accessor :name, :favorite_language
By the way, these aren’t special Ruby syntax; they are methods
that write the getters and setters for you
Ruby uses lots of metaprogramming: programs that write
programs
Access controls





Public methods can be called from anywhere
Protected methods can be called only within the class
and its subclasses
Private methods cannot be called with an explicit
receiver, only with an implicit self
In Ruby, methods are public by default
The functions public, protected, and private can be
called with or without arguments

With arguments, they set the access of the named methods


Example: private :dump, :swear
With no arguments, they set the default access for all
subsequent methods
eval

eval executes a string


Here’s how you don’t want to use this:



Example: eval "puts x + 2"
eval gets
This can be a serious security risk
Here’s what Ruby does about this:


All data that comes from the outside world, and all data
derived from that data, can automatically be marked as tainted
Ruby has five $SAFE levels, each of which has a long list of
things you cannot do with a tainted object
printf and friends

printf format_string, value, …, value






Formats are % length code for most things,
% length . fractional_digits code for floats
%d  decimal, %o  octal, %x  hex, %b  binary,
%f  float, %s  string
Negative lengths mean left justified
Various other controls
Example: printf "pi = %8.4f", 3.141592 
pi.=…3.1416
The (equivalent) methods sprintf and format take the
same parameters as printf, but return the resultant
string rather than printing it
Some File < IO methods











gets – get a line of text
getc – get a character of text (as ASCII; use .chr)
ungetc – put back a character
pos – the current character position in the input stream
lineno – the number of times gets has been called
pos= – move to the given position in the file
rewind – move to the beginning of the file
readlines – read the stream as an array of strings
write(string), print(string), <<(string) – write at the current
position
eof? – test if at the end of file
closed? – test if the file has been closed
Some File methods




rename(oldname, newname) – rename a file
read(filename) – read the entire file as a single string
readlines(filename) – read the entire file as an array of strings
open(filename, mode) –









with no block, a synonym for File.new
with a block, the file is passed to the block, and automatically closed when the
block finishes
Modes: "r" read, "r+" read and write, "w" write, "a" append
exists?(filename) – test if a file with that name exists
writable?(filename) – test if the file can be written
directory?(filename) – test if the file is a directory
zero?(filename) – test if the file is empty
size(filename) – returns the size of the file
mtime(filename) – returns the modification time of the file
Streams



The following constants refer to standard I/O streams:
STDIN, STDOUT, STDERR
The following variables are initially set to the
corresponding constants: $stdin, $stdout, $stderr
In addition, $defout (initially equal to $stdout) is
where output with no specified destination is sent
Some String methods





ljust(length), center(length), rjust(length) – left
justify, center, or right justify the string by padding with
spaces
downcase, upcase, swap, capitalize – modify
capitalization
include?(s_or_c) – tests whether the string includes the
given string or character
index(s_or_c [, offset]) – returns the index after
offset(or nil) at which the gives string starts
rindex(s_or_c [, limit]) – returns the last index (before
limit), or nil, at which the string starts
Some more String methods




strip – remove leading and trailing spaces
chop – remove the last character (also chop! is
destructive)
chomp – remove the last character if it is a newline
(also chomp!)
tr(chars, replacement) – replace the characters in
chars with the corresponding characters in
replacement; accepts ch1-ch2 notation
Some Array methods










min, max – return the smallest or largest element
uniq – return an array with no duplicate elements
compact – return an array with no nil elements
sort – return a sorted array
& – perform an intersection (only elements in both)
| – perform a union (elements in either)
grep(regexp) – return elements matching the pattern
push(element) – add the element to the end of the array
pop – remove and return the last element
shift – remove and return the first element
Chaining

Nondestructive methods can usually be chained


Example: x = gets.chomp.strip.downcase
Many destructive methods return nil if they make no
changes in the receiver, hence cannot be chained

Example: x = gets.chomp!.strip!.downcase! will result in
a runtime error
Context





def do_it
a = [1, 2, 3, 5, 8, 13, "hi"]
x = 4 # local variable
a.my_each { |v| print v * x, "; " }
end
do_it
 4; 8; 12; 20; 32; 52; hihihihi;
Notice that the print v*x statement is being executed in the
my_each method, not in the do_it method
However, x is local to the do_it method
How can this be?


Answer: The block carries its context along with it
A block is a closure
More iterators


collection.each_index – iterate over the indices of a collection
collection.each_with_index – iterate over the values in a
collection, along with their indices






Example: lineup.each_with_index { |man, pos| print pos, man }
hash.each_key – iterate over keys
hash.each_value – iterate over values
hash.each_pair – iterate over key-value pairs
collection.select { |v| condition } – choose only items that
meet the condition
collection.map { |v| transformation } – create a new
collection with the transformation applied to each item
Procs

A proc is a procedure that is stored in a variable


p = Proc.new { |x, y, z| puts 100 * x + 10 * y + z }



Call a proc by using the variable’s call method
p.call 14, 9, 2
1492
max = Proc.new do |a, b|
if a > b then a else b end
end


puts max.call(0.8, 0.12)
0.8
Procs are closures, too

def scoper p
x=3
p.call
end

x = 77
p = Proc.new { puts x }
x = 19
scoper p

19



Procs as parameters


A block passed as a parameter to a function becomes a
Proc
The formal parameter must be last, and is prefixed with
an ampersand



def foo &b
b.call
end
foo { puts "Hi!" }
Hi!
Reflection







The class method returns the class of an object
The superclass method returns the superclass of an object
The name method returns the name of a class
The new method creates a new object of a class
The methods method returns the methods than an object knows
how to respond to
The instance_variables method returns the attributes of an
object
There are many other methods to examine (and modify!) a Ruby
program while it is executing
Undefined methods



If an undefined method is called, Ruby raises a
NoMethodError
If you supply a method_missing method for your
object, Ruby will call this instead
Example:



def method_missing(name, *args)
puts "Call of missing method" +
" #{name}(#{args.join ', ' })"
end
fribble 2, :ace
Call of missing method fribble(2, ace)
Adding methods to a class




To add (or replace) a method to a class, just open up the class
definition again and define the method
You can even do this with Ruby’s built-in classes
class Array
def every_other
i=0
while i < self.length
yield self[i]
i += 2
end
end
end
[1, 2, 3, 5, 8, 13].every_other {|v| print v, "; "}

1; 3; 8;
Modules

Classes in Ruby, as in Java, may extend only one other
class




Example: class Enterprise < Starship
Everything in the superclass is available in the subclass
A module is defined just like a class (using the word
module instead of class)
Modules cannot be instantiated, but they may be
included in a class


Including a module is like copying the code into the class
Example:
class Enterprise < Starship
include Location
...
Metaprogramming


Metaprogramming is using programs to write
programs
Example uses:




You want to add “boilerplate” code to every method
You want to “wrap” functions so that they print to a log
when they are called and when they return
You want to examine a database and automatically create
methods to access that database
You can do metaprogramming in any language, but...

In Ruby the program can make the changes to itself, as it
runs
The command line


irb starts an interactive Ruby interpreter
ruby starts Ruby, with input from the command line
 End with an end-of-file character (^D or F6)



ruby filename.rb executes the given file
ruby -e quotedString executes the quoted string



Not actually very useful
Example: ruby -e 'puts "The time is #{Time.now}" '
ruby -v tells you Ruby’s version number
On Unix, if the first line of a Ruby file is
#!/usr/bin/ruby (or wherever ruby is located), the file
can be executed by just entering the file name
Looking ahead



Ruby on Rails (or just Rails) is the “killer app” that
catapulted Ruby to prominence
Web applications are extremely complex server-side
programs that communicate with the user’s browser
using HTML, XML, and CSS, do session
management, and handle a server-side database
Rails uses metaprogramming to write your web
application for you


It’s hard to convey just how much work this saves
The downside? You still have to understand the programs
that it writes
Tutorials


Your textbook has an introduction to Ruby
There are many Ruby tutorials on the web--here are some of
special interest

http://www.tutorialspoint.com/ruby/


http://www.math.umd.edu/~dcarrera/ruby/0.3/


Pretty complete
http://www.infoq.com/minibooks/ruby


Short enough to read through
http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm


Very similar in style to the w3schools tutorials
A favorite free online book
http://poignantguide.net/ruby/

For something just a “little bit different” :)
The End
Download