Ruby (Bet you can’t do this in Java!) 6-Nov-15 “Hello World” in Ruby  puts "Hello World!"

Download Report

Transcript Ruby (Bet you can’t do this in Java!) 6-Nov-15 “Hello World” in Ruby  puts "Hello World!"

Ruby (Bet you can’t do

this

in Java!)

2-May-20

“Hello World” in Ruby

puts "Hello World!"

Euclid’s algorithm

 def euclid x, y while x != y x if x > y then x -= y end if y > x then y -= x end end 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     Decimal: 3405691582 Hex: 0xCAFEBABE or 0XCAFEBABE Octal: 031277535276 or 0o31277535276 Binary: 0b11001010111111101011101010111110 or 0B

etc.

Numbers larger than four bytes are automatically treated as Bignum objects For readability, numbers may contain (but not begin or end with) underscores  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

} #@

variable

, and allow the usual escape characters In a singly quoted string, \' and for 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

Ruby uses Ruby uses ++ and - :: to mean the same as =~ and !~ . in Java for Perl-style regular expressions ** is the exponentiation operator + is used to concatenate

strings

 There is a to_s method for converting other things to strings .. is an inclusive range, ... is an exclusive range   So 1..4

0..k

and 1...5

both mean is a range object, but 1, 2, 3, 4 [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 !

,  Precedence is !

&& > && , || and also > || , but not not > and , and == or , or

Assignment and alias statements

  Assignment statements use

=

,

+=

,

*=

, etc.

 You can have multiple assignment: values of x and y x, y = y, x swaps the 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

“ then ” is required to separate condition from code

statement

if

condition

else

code

end

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 end

code

Cases do

not

break fall through; no is needed Comparisons use

expr_n

===

expr_1

and not the other way around  

expr_n

=== meanings

expr_1

has many     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  while

condition statements

end do  begin

statements

end while

condition

 until end

condition statements

 begin

statements

end until

condition

 for

variable statements

end in

range

do  loop do

statements

end 

statement

while

condition

statement

until

condition

 loop {

statements

}   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

Within a block,

next

jumps to just before the loop test 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 raise raise

message

raises a

RuntimeError

exception exception

,

raises an error of the given type

message

  

rescue rescue rescue

variable ExceptionType

, ...,

ExceptionType ExceptionType

, ...,

ExceptionType

=>

 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:  def

method_name

(

parameter1

,

statements

end

...

,

parameterN

) Defining a class method:  def

Class_name

.

method_name

(

parameter1

,

statements

end

...

,

parameterN

) Parentheses are optional A method may contain explicit return and/or return

value

statements A method may return multiple values: A method which reaches the end executed (often nil ) return x, 2*x, x**2 returns the value of the last statement A method may also have a block as an (invisible) parameter  The block is not mentioned in the def evaluates the yield statement line, but is executed when the method

Defining classes

 class Employee < Person # ‘<‘ means “extends” @@number = 0 # class variable attr_reader :name # creates a getter for @name def initialize(name) end @name = name @@number += 1 end # this is the constructor  secretary = Employee.new("William")

Calling methods

    Methods may be called as in Java  puts("x = #{x}") Parentheses are usually unnecessary  puts "x = #{x}" All values are objects, and may have methods  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

or

object

.

iterator statements

end { |

value

|

statement

do |

value

| }

 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

n.downto(

limit

)

times – step from

n

down to and including

limit

n.upto(

limit

)

– step from

n

string.each_line

up to and including – get each line from a string

limit

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}" }  Output: 1 1 2 3 5 8 13  a.each do |i| print " #{i}" end  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 end each_byte { |b| yield b.chr } 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 end yield i1 i1, i2 = i2, i1 + i2 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

end yield 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 1 2 3  count_to_3 { |result| puts result }

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] p a  [1, 2, 3, 5, 8, 13, "hi", 21, 34] Arrays can be treated as stacks, with a.push(v) The join(

string

) and v = a.pop

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]  :yellow h[:apple] = :green p h  {: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 The only parameter to undef is the method name 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  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

When you

call

the setter, there is

no space

before the = in the header 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

called with or without arguments can be   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 Example: eval "puts x + 2" Here’s how you

don’t

want to use this:  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

%d  %f  decimal, %o float, %s   octal, string code for floats %x  hex, %b  binary, 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 getc – get a line of text – get a character of text (as ASCII; use ungetc – put back a character .chr

) 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

) read(

filename

) – rename a file – 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

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

) zero?(

filename

) – test if the file is a directory – test if the file is empty size(

filename

) – returns the size of the file mtime(

filenam

e) – returns the modification time of the file when the

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

limi

t

), 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 end # local variable a.my_each { |v| print v * x, "; " } do_it  4; 8; 12; 20; 32; 52; hihihihi; Notice that the print v*x my_each statement is being executed in the 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  Call a proc by using the variable’s call method

p = Proc.new { |x, y, z| puts 100 * x + 10 * y + z }

  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

object, Ruby will call this instead method for your 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

end yield self[i] i += 2 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

class  Example: class Enterprise < Starship other  Everything in the superclass is available in the subclass A module module is defined just like a class (using the word 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

)  Not actually very useful

ruby

filename

.rb

ruby -e

quotedString

 executes the quoted string Example: ruby -e 'puts "The time is #{Time.now}" '

ruby -v

executes the given file 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/      Very similar in style to the w3schools tutorials http://www.math.umd.edu/~dcarrera/ruby/0.3/  Short enough to read through http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm

 Pretty complete http://www.infoq.com/minibooks/ruby  A favorite free online book http://poignantguide.net/ruby/  For something just a “little bit different” :)

The End