Intro to Ruby

Class 2

Welcome!

Girl Develop It is here to provide affordable and accessible programs to learn software through mentorship and hands-on instruction.

Some "rules"

  • We are here for you!
  • Every question is important
  • Help each other
  • Have fun

Homework Discussion

How was last week's homework? Do you have any questions or concepts that you'd like to discuss?

Review

  • Arithmetic and variables
  • Data types
  • Text editor, command line, and ruby shell

What we will cover today

  • Boolean Expressions and Conditionals
  • Loops
  • Collections

Booleans

A boolean is a basic data type. It can have only two values: true or false.

Boolean Expressions

Code that compares values and returns True or False is called a Boolean expression

  • Test for equality by using `==`. We can't use `=` because that is used for assignment
  • Test for greater than and less than using `>` and `<`

Boolean Expressions cheat sheet

a == b a is equal to b
a != b a does not equal b
a < b a is less than b
a > b a is greater than b
a <= b a is less than or equal to b
a >= b a is greater than or equal to b

Learn more about logical operators in Ruby here.

Boolean Expressions practice


a = 3
b = 4
puts a != b
puts a <= 3
puts a >= 4
a = 5
b = 5
puts a == b
c = a == b # Combine comparison and assignment
puts c
puts 3 < 5
            

Remember: Equals does not equal "equals equals"

Further reading on boolean expressions...

Boolean Expressions

A boolean expression evaluates to true or false. It can also have multiple parts, joined by AND (&&) or OR (||).

EXPRESSION EVALUATES TO
true && true true
true && false false
false && false false
true || true true
true || false true
false || false false
not (true && false) true

Further practice on boolean expressions...

Let's Develop It

Take a few minutes and experiment with boolean expressions in IRB. You can start with the examples below.


true && false
1 == 1 && 2 > 37
"boop" == "bip" || 7 == 8
false || true
89 > 88 || 89 < 90
true || not(1 == 1 || 2 == 65)
          

Putting Booleans to Work

So, what's the value of knowing if a statement is true or false? Often, you'll use that to control whether a piece of code will execute or not.


user_guess = gets.chomp.to_i
secret_number = 312

if user_guess < secret_number
puts "Too low!"
elsif user_guess > secret_number
puts "Too high!"
else
puts "You guessed it. Wow maybe you're psychic...."
end
          

Can you tell what this code does?

Conditionals

When we want different code to execute depending on certain criteria, we use a conditional

We achieve this using if statements and boolean expressions.


if x == 5
puts 'x is equal to 5'
end
          

Conditionals

We often want a different block to execute if the statement is false. This can be accomplished using else.


if x == 5
puts 'x is equal to 5'
else
puts 'x is not equal to 5'
end
          

Conditionals

The following shows some examples of conditionals with more complex boolean expressions:


# And
if x > 3 && y > 3
puts 'Both values are greater than 3'
end

# Or
if x != 0 || y != 0
puts 'The point x,y is not on the x or y axis'
end

# Not
if not(x > y)
puts 'x is less than y'
end
          

Chained conditionals

Conditionals can also be chained.

Chained conditionals use elsif to test if additional statements are true. The single 'else' action will only happen if all preceding conditions are false.

For example:


if x > 10
puts "x is greater than 10"
elsif x <= 10 && x > 0
puts "x is a number between 1 and 10"
else
puts "Wow, don't be so negative, dude"
end
          

Let's Develop It

Write a program in your text editor that uses conditionals and user input to allow the user to play an adventure game.

"gets.chomp" is the value of user input at the command line, with the trailing whitespace chomped off. To do math with it, convert it to an integer with the ".to_i" method


            input = gets.chomp.to_i
          

Run your program by calling it with Ruby from the command line.


            $ ruby program_name.rb
          

Let's Develop It Example


# adventure.rb
puts "A vicious dragon is chasing you!"
puts "Options:"
puts "1 - Hide in a cave"
puts "2 - Climb a tree"

input = gets.chomp

if input == '1'
puts "You hide in a cave. The dragon finds you and asks if you'd like to play Scrabble. Maybe it's not so vicious after all!"
elsif input == '2'
puts "You climb a tree. The dragon can't find you."
else
puts "That's not a valid option."
end
          


#command line
ruby dragon.rb
          

Loops

It is often useful to perform a task and to repeat the process until a certain point is reached.

The repeated execution of a set of statements is called iteration, or, more commonly, a loop.

One way to achieve this, is with the while loop.


x = 10

while x > 0
puts "Loop number #{x}"
x = x - 1
end

puts 'Done'
            

While Loops


x = 10

while x > 0
puts "Loop number #{x}"
x = x - 1
end
          

The while statement takes a condition, and as long as it evaluates to true, the code block beneath it is repeated. This creates a loop.

Without the `x = x - 1` statement, to increment the value of x, this would be an infinite loop :( :( :(

While loops

Consider the following example that uses a while loop to sing you a song.


num_bottles = 99

while num_bottles > 0
puts "#{num_bottles} bottles of beer on the wall,
#{num_bottles} bottles of beer, take one down, pass it
around, #{num_bottles - 1} bottles of beer on the wall!"

num_bottles = num_bottles - 1
end
          

"#{num_bottles}" is an example of string interpolation

Let's Develop It

  • Write a program that obtains user input like the last program
  • This program should not exit until the user says it should (maybe by entering "quit"?)
  • Use a loop!
  • You can use the next slide as an example.

Let's Develop It: Example


# loopy.rb
loopy = true

while loopy == true
puts "Are we having fun yet?"
puts "Answer 'true' or 'false'."
user_input = gets.chomp
if user_input == 'false'
loopy = false
end
end
          

Learn more about loops in Ruby here.

Each loops

The most commonly used type of loop in Ruby is an each loop. It uses the .each method to iterate over a collection of elements, doing work to each one.

First, we need a collection. We use a range of numbers to loop over.


(0..5).each do |i|
puts "Value of i is #{i}"
end
            

Each loops


(0..5).each do |i|
puts "Value of i is #{i}"
end
            

The loop has three parts:

  • The collection that will be looped through, in this case a range- "(0..5)"
  • The name to give each element when the loop begins again - "i" - in the pipes "| |"
  • The code to execute with the element - the puts statement

We will revisit the each loop when we have a better understanding of collections.

Collections

There are three main types:

  • Ranges
  • Arrays
  • Hashes

new_range = (1..10)

new_array = [1, 3, 5]

new_hash = {"dog" => "snoopy", "bird" => "woodstock"}
          

Ranges


inclusive_range = (1..3)  # contains 1, 2, 3
exclusive_range = (1...3) # contains 1, 2
letter_range = ('a'..'e') # contains 'a', 'b', 'c', 'd', 'e'
          

Ranges are simply the range of values between the given first and last elements.

Inclusive ranges have two dots, and include the last element. Exclusive ranges have three dots, and do not include the last element.

Ranges need to be defined from lowest value to highest.

Ranges

Try out these range methods in IRB.


(1..99).max
('b'...'z').include?('j')
(890..902).begin
(890..902).first(4)
(890..902).last(3)
(890..902).end
(28..22).min

('a'...'g').each do |l|
puts "#{l} is a pretty good letter"
end

(22..28).to_a
          

Learn more about ranges here.

Arrays

Arrays have square brackets and can be filled with any type of object: integers, floats, strings, even other arrays or hashes.


new_array = [1, 3, 5, 89, 212, 7, -100]
arr = ["wow", "woooo", "zowie"]
array = Array.new #will have no elements inside it initially
varied_array = ["one", 2, "THREE", 0.4, ["five", 6]]

# methods to get information about an array
new_array.length
new_array.count
arr.include?("yee ha")
          

Arrays are a great way to keep track of information that changes frequently.

Accessing Elements in an Arrays

Arrays are ordered and are integer-indexed, starting at 0.

Elements can be accessed by their position.


new_array = [1, 3, 5, 89, 212, 7, -100]
arr = ["wow", "woooo", "zowie"]

new_array[0]    # returns the zeroth element
arr[2]          # returns the third element
arr[-1]         # returns the last (1st from the end) element
new_array.last  # returns the last element
new_array[1..2] # returns the second and third elements
arr.first       # returns the first element
          

Adding & Deleting From Arrays

Adding and removing items to an array can be done in a variety of ways. These are the most common.


arr = ["wow", "woooo", "zowie"]

#add
arr.push("hot diggity") # adds argument as last element
arr << "yikes"          # adds argument as last element

#remove
arr.delete("wow")       # deletes the element that matches argument
arr.pop                 # removes and returns the last element
          

More Array Methods

Arrays are used a lot in Ruby. There are a lot of cool methods available for them.


arr = ["dog", "cat", "turtle", "parakeet", "ferret"]

arr.index("dog")  # returns the index of the element that matches argument
arr.join          # returns a string made up of all the elements
arr.clear         # removes all elements from the array
arr.reverse       # returns new array with same elements, reversed
arr.shuffle       # returns new array with same elements, shuffled
arr.uniq          # returns a new array with only unique elements
arr.size          # returns the number of elements in the array
arr.empty?        # returns a boolean
          

Learn more about arrays here.

Hashes

Hashes have curly braces and hash rockets and can be filled with any data type: integers, floats, strings, even arrays and hashes.


grades_hash = { "Jane Doe" => 10, "Jim Doe" => 6, "Jan Doe" => 8}
new_hash = { 1 => "a", "d" => 12, "f" => 35 }

# methods to find information about hashes
new_hash.length
grades_hash.count
grades_hash.size
grades_hash.has_key?("Jan Doe")
new_hash.has_value?(35)

          

Syntax:

{ key => value, key => value }

Accessing Elements in Hashes

Hashes are unordered. Hashes are like dictionaries, with unique key / value pairs.

Because hashes can have any type of object as an idex, and are unordered, we must access values by their key.


grades_hash = { "Jane Doe" => 10, "Jim Doe" => 6, "Jan Doe" => 8}
new_hash = { 1 => "a", "d" => 12, "f" => 35 }

grades_hash["Jane Doe"]   # returns 10, the value of this key
new_hash["d"]             # returns 12, the value of this key
grades_hash.first         # returns first key/value pair... probably
          

Adding & Removing from Hashes


new_hash = { 1 => "a", "d" => 12, "f" => 35 }

# add
new_hash["z"] = 43   # adds a new key/value pair "z" => 43

#remove
new_hash.delete("d") # removes key/value pair with specified key
new_hash.clear       # removes all key/value pairs
          

More Hash methods


chapters = {"My Early Home" => (1..15), "The Hunt" => (16..28),
        "My Breaking In" => (29..46), "Birtwick Park" => (46..60)}

chapters.count      # returns number of key/value pairs in hash
chapters.keys       # returns an array of all the keys in hash
chapters.has_key?("How It Ended")  # returns a boolean
chapters.to_a       # converts hash to an array of arrays
chapters.invert     # returns new hash with old one's values
                  # as keys and keys as values
            

Learn more about hashes here.

Enumerable

Arrays and Hashes are both members of the Enumerable class. There are a lot of cool methods available for Enumerable, including each.

.each with Ranges

This is the simplest!


(3..8).each do |n|
puts n * 4
end
          

.each with Arrays

Can be simple or more complex, depending on the array.


pets_array = ["dog", "cat", "turtle", "parakeet", "ferret"]

pets_array.each do |p|
puts "I like #{p}s!!"
end


deep_array = [["mountain", "desert"], ["ocean", "sky"]]

deep_array.each do |p|
puts "I like #{p.first}s!!"  # each element is also an array
end
          

.each with Hashes

Each element has a key and value that needs to be dealt with.


grades_hash = { "Jane Doe" => 10, "Jim Doe" => 6, "Jan Doe" => 8}

grades_hash.each do |key, value|
puts "#{key}'s grade is #{value}"
end
          

Let's Develop It

Write a program that prints out every number between 1 and 1000 that is divisible by 7.


Hint: the modulo operator, %, will be helpful.

Enumerable

Visit this page and copy the contents of the Gist to a local file. Save it as pets.rb. We'll work with it together in IRB.

Enumerable: Reduce

Returns the product of running the operator on all elements of the enumerable.


(1..4).reduce(:*)   # returns 1 * 2 * 3 * 4
(1...5).reduce(:+)  # returns 1 + 2 + 3 + 4
(2...5).reduce(:**) # returns 2 ** 3 ** 4
          

Enumerable: Collect and Map

Returns an array with the results of running the block on each element. Can be used interchangably.


$pets.collect{|p| p[:name]}      # returns array of all pet names
$pets.collect{|p| p[:legs]}.reduce(:+) # returns sum of all pet legs
          

Enumerable: Reject

Returns an array with all elements that did not meet the critera in code block.


$pets.reject{|p| p[:talents].include? "napping" }
  # returns array of pets whose talents do not include napping
          

Let's Develop It

How many of our pets are nocturnal?

Let's Develop It- Sample Code

How many of our pets are nocturnal?


$pets.reject{|p| p[:nocturnal]== false}.count
            

Questions?

Homework

Practice: Find two interesting methods for Enumerable (via Ruby Docs) and write a little program that uses them for arrays or hashes. Do any one the exercises at the end of Chapter 6 of Learn to Program.

Prep: Read Chapter 8 of Learn To Program- don't try to do the exercises at the end yet, though.