Monday, April 11, 2016

Ruby_Lesson_Methods, Blocks, & Sorting

A method to the madness
1.Why Methods?
A method is a reusable section of code written to perform a specific task in a program. You might be wondering why you need to separate your code into methods, rather than just writing everything out in one big chunk. It turns out there are a few good reasons to divide your programs into methods:
  1. If something goes wrong in your code, it's much easier to find and fix bugs if you've organized your program well. Assigning specific tasks to separate methods helps with this organization.
  2. By assigning specific tasks to separate methods (an idea computer scientists call separation of concerns), you make your program less redundant and your code more reusable—not only can you repeatedly use the same method in a single program without rewriting it each time, but you can even use that method in another program.
def prime(n)
  puts "That's not an integer." unless n.is_a? Integer
  is_prime = true
  for i in 2..n-1
    if n % i == 0
      is_prime = false
    end
  end
  if is_prime
    puts "#{n} is prime!"
  else
    puts "#{n} is not prime."
  end
end

2.Method Syntax
Methods are defined using the keyword def (short for "define"). Methods have three parts:
  1. The header, which includes the def keyword, the name of the method, and any arguments the method takes.
  2. The body, which is the code block that describes the procedures the method carries out. The body is indented two spaces by convention (as with for, if, elsif, and else statements)
  3. The method ends with the end keyword.
Here's an example of what the syntax would look like for a simple function, welcome, that just prints "Welcome to Ruby!" to the console:
def welcome
  puts "Welcome to Ruby!"
end
4.Call It!
Defining a method is great, but it's not much use to you unless you call it. For example, if you call a method called cartoon_fox, Ruby will start looking for the method with that name and try to execute the code inside it. More Complex Methods
5.Parameters and Arguments
If a method takes arguments, we say it accepts or expects those arguments. We might define a function, square, like so:
def square(n)
  puts n ** 2
end
and call it like this:
square(12)
# ==> prints "144"
6.Splat!
Speaking of not knowing what to expect: your methods not only don't know what arguments they're going to get ahead of time, but occasionally, they don't even know how many arguments there will be.
Let's say you have a method, friend, that puts the argument it receives from the user. It might look something like this:
def friend(name):
  puts "My friend is " + name + "."
end
This is great for just one friend, but what if you want to print out the user's friends, without knowing how many friend names the user will put in ahead of time?
The solution: splat arguments. Splat arguments are arguments preceded by a *, which signals to Ruby: "Hey Ruby, I don't know how many arguments there are about to be, but it could be more than one."
def what_up(greeting, *bros)
  bros.each { |bro| puts "#{greeting}, #{bro}!" }
end
what_up("What up", "Justin", "Ben", "Kevin Sorbo")

7.Let's Learn Return
Sometimes we don't just want a method to print something to the console, but we actually want that method to hand us (or another method!) back a value. For that, we use return.
def double(n)
  return n * 2
end

output = double(6)
output += 2
puts output
The return of Blocks
8.Blocks Are Like Nameless Methods
Most methods that you've worked with have defined names that either you or someone else gave them (i.e. [array].sort(), "string".downcase(), and so on). You can think of blocks as a way of creating methods that don't have a name. (These are similar to anonymous functions in JavaScript or lambdas in Python.)
Blocks can be defined with either the keywords do and end or with curly braces ({}).
1.times do
  puts "I'm a code block!"
end
1.times { puts "As am I!" }

11.Using Code Blocks
A method can take a block as a parameter. That's what .each has been doing this whole time: taking a block as a parameter and doing stuff with it!
Passing a block to a method is a great way of abstracting certain tasks from the method and defining those tasks when we call the method. Abstraction is an important idea in computer science, and you can think of it as meaning "making something simpler." Imagine if when you wanted to house hunt, you had to say, "Honey, let's go look at configurations of concrete, plywood, and vinyl siding." That'd be crazy! Just like saying "house" simplifies listing its components, using a block to define the task you want the method (like .each) to do simplifies the task at hand.
[1, 2, 3, 4, 5].each { |i| puts 5*i }
Sorting with Blocks
12.Introduction to Sorting
my_array = [3, 4, 8, 7, 1, 6, 5, 9, 2]
my_array.sort!
14.The Combined Comparison Operator
We can also use a new operator called the combined comparison operator to compare two Ruby objects. The combined comparison operator looks like this: <=>. It returns 0 if the first operand (item to be compared) equals the second, 1 if first operand is greater than the second, and -1 if the first operand is less than the second.
A block that is passed into the sort method must return either 1, 0, -1. It should return -1 if the first block parameter should come before the second, 1 if vice versa, and 0 if they are of equal weight, meaning one does not come before the other (i.e. if two values are equal).
book_1 = "A Wrinkle in Time"
book_2 = "A Brief History of Time"
book_1 <=> book_2

15.Getting Technical
The sort method assumes by default that you want to sort in ascending order, but it accepts a block as an optional argument that allows you, the programmer, to specify how two items should be compared.
books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]
# To sort our books in ascending order, in-place
books.sort! { |firstBook, secondBook| firstBook <=> secondBook }
# Sort your books in descending order, in-place below
books.sort! {|firstBook, secondBook| secondBook <=> firstBook}

Project
def alphabetize(arr, rev=false)
  if rev
    arr.sort { |item1, item2| item2 <=> item1 }
  else
    arr.sort { |item1, item2| item1 <=> item2 }
  end
end
books = ["Heart of Darkness", "Code Complete", "The Lorax", "The Prophet", "Absalom, Absalom!"]
puts "A-Z: #{alphabetize(books)}"
puts "Z-A: #{alphabetize(books, true)}"

1.Default Parameters
As show in the example above, rev (for "reverse") that will default to false if the user doesn't type in two arguments.
2.Sorting
In Ruby, there are two sorting methods, .sort or sort!. The first method, .sort, simply returns a sorted array while leaving the original array alone. The second method, .sort!, modifies the actual array.





No comments :

Post a Comment