23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

36
Mar 27, 2 022 Ruby! (Bet you can’t do this in Java!)

Transcript of 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Page 1: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Apr 20, 2023

Ruby!

(Bet you can’t do this in Java!)

Page 2: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Ruby is dynamic In Ruby, anything can be changed, anytime Variables don’t have a type; the type belongs to the value

currently in the variable Methods can be defined—and undefined Methods can be added to a class—at run time Methods can be added to individual objects Strings can be compiled and executed I’m sure there’s more, but you get the idea

Why was Ruby written? The author, Yukihiro "Matz" Matsumoto, wanted a language that

was fun to program in!

Page 3: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Defining and undefining methods

To define a method:def name (parameters) body // the last value is the returned value end

To remove a method; undef name To add an instance method to an existing class, first “open”

the class class String def nchars length endend

Page 4: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Class and object methods

To add a class method while inside the Person class:def self.species ‘human’end

To add a class method from elsewhere:def Person.species ‘human’end

To add a method to an individual object:def oscar.mood ‘grouchy’end

Page 5: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Numbers Numbers may be written in decimal, hexadecimal, octal, or

binary Decimal: 3405691582 Hex: 0xCAFEBABE or 0XCAFEBABE Octal: 031277535276 or 0o31277535276 Binary: 0b11001010111111101011101010111110 or 0Betc.

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

Page 6: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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 @nameend

You can write setters: def name=(new_name) @name = new_nameend

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 = "Saj“

Yes, we are calling the method name= !

Page 7: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 8: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 9: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 10: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 11: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 12: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 13: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Regular expressions

Ruby has regular expressions, almost identical to the way they are done in Perl

Example (from the textbook): hamlet = "The slings and arrows of outrageous fortune."hamlet.scan(/w+/)

["The", "slings", "and", "arrows", "of", "outrageous", "fortune"]

Page 14: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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] = :greenp 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

Page 15: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Loops in Ruby Ruby has several loops

while condition do statementsend

begin statementsend while condition

until condition statementsend

begin statementsend until condition

for variable in range do statementsend

statement while condition

statement until condition

However, loops are not used as often in Ruby as in other languages

Instead, Ruby programmers use iterator methods

Page 16: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 17: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 18: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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 multiline blocks

Page 19: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Blocks

A block is a chunk of code that can be passed as a parameter to a method

Blocks are basically function literals 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

Page 20: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Simplest use of yield def three_times

puts "---------- three_times“ yield yield yieldend

three_times { puts "hello" }

---------- three_timeshellohellohello

Page 21: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

My version of loop def my_loop yield while trueend

a = [1, 2, 3, 5, 8, 13, "hi"]my_loop do break if a.empty? print a.popendputs "Done" hi1385321Done

Page 22: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Fibonacci numbers

def fibonacci_upto n i1, i2 = 1, 1 while i1 < n yield i1 i1, i2 = i2, i1 + i2 endend

fibonacci_upto(100) { |f| print " ", f } 1 1 2 3 5 8 13 21 34 55 89

Page 23: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Passing a parameter to the block def count_to n

puts "---------- count_to #{n}" for i in 1..n yield endend

count_to 3 { puts "hello" }

---------- count_to 3hellohellohello

Page 24: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Returning a value from a coroutine def count_to_3

puts "---------- count_to_3“ yield 1 yield 2 yield 3end

count_to_3 { |result| puts result }

---------- count_to_3123

Page 25: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 26: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 27: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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 endend puts max.call(0.8, 0.12) 0.8

Page 28: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Procs are closures, too

def scoper p x = 3 p.callend

x = 77 p = Proc.new { puts x } x = 19 scoper p

19

Page 29: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

foo { puts "Hi!" } Hi!

Page 30: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 31: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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)

Page 32: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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 endend

[1, 2, 3, 5, 8, 13].every_other {|v| print v, "; "}

1; 3; 8;

Page 33: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

...

Page 34: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

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

Page 35: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

Rails

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

Page 36: 23-Oct-15 Ruby! (Bet you can ’ t do this in Java!)

The End