Personal Notes on Learning Ruby 3
Classes
- class
- is_a
- new
- State and Behaviour
puts 1.class
puts "".class
puts [].class
#=> Fixnum
#=> String
#=> Array
puts 1.is_a?(Integer) # true
puts 1.is_a?(String) # false
1.class.class # Class
# Create an instance of Object
Object.new
All classes shall have names that begin with a capital letter.
class Rectangle
end
State and Behaviour
class Rectangle
def perimeter
end
end
class Rectangle
def perimeter
2 * (@length + @breadth)
end
end
Ruby follows a two-space indentation convention and sections of code are typically closed using the keyword end.
@ symbol placed in front of variable is a convention which designates them as being a part of the state of the class, or they are the "instance variables of the class." This means that every instance of the class Rectangle will have its own unique copies of these variables and is in effect, a distinct rectangle.
class Rectangle
def initialize(length, breadth)
@length = length
@breadth = breadth
end
def perimeter
2 * (@length + @breadth)
end
def area
@length * @breadth
end
end
n = Rectangle.new(2,5)
n.perimeter #=> 14
n.area #=> 10
Rectangle.new(4,6).area #=> 24
Arraying arguments
- splat operator
# with list
def add(*numbers)
numbers.inject(0) { |sum, number| sum + number }
end
puts add(1)
puts add(1, 2)
puts add(1, 2, 3)
puts add(1, 2, 3, 4)
# splat an array
def add(a_number, another_number, yet_another_number)
a_number + another_number + yet_another_number
end
numbers_to_add = [1, 2, 3] # Without a splat, this is just one parameter
puts add(*numbers_to_add) # Try removing the splat just to see what happens
Exercises
- abs
- round
- inject
- shift
- pop
Create a method called introduction that accepts a person's age, gender and any number of names, then returns a String
def introduction(age, gender, *names)
name = names.join(" ")
"Meet "+ name + ", who's "+ age.to_s + " and " + gender
end
# is the same as
def introduction(age, gender, *names)
"Meet #{names.join(' ')}, who's #{age} and #{gender}"
end
# Naming parameters
def add(a_number, another_number, options = {})
sum = a_number + another_number
sum = sum.abs if options[:absolute]
sum = sum.round(options[:precision]) if options[:round]
sum
end
puts add(1.0134, -5.568)
puts add(1.0134, -5.568, absolute: true)
puts add(1.0134, -5.568, absolute: true, round: true, precision: 2)
# add, subtract and calculate assignment
def add(*numbers)
numbers.inject(0) { |sum, number| sum + number }
end
def subtract(*numbers)
sum = numbers.shift
numbers.inject(sum) { |sum, number| sum - number }
end
def calculate(*arguments)
# if the last argument is a Hash, extract it
# otherwise create an empty Hash
options = arguments[-1].is_a?(Hash) ? arguments.pop : {}
options[:add] = true if options.empty?
return add(*arguments) if options[:add]
return subtract(*arguments) if options[:subtract]
end
# shift: Removes the first element of self and returns it (shifting all other elements down by one).
args = [ "-m", "-q", "filename" ]
args.shift #=> "-m"
args #=> ["-q", "filename"]
# pop: Removes the last element from self and returns it
a = [ "a", "b", "c", "d" ]
a.pop #=> "d"
a.pop(2) #=> ["b", "c"]
a #=> ["a"]
Lambdas
l = lambda { "Do or do not" }
puts l.call #=> Do or do not
# lambda with parameter
l = lambda do |string|
if string == "try"
return "There's no such thing"
else
return "Do or do not."
end
end
puts l.call("try") # Feel free to experiment with this
# Increment 1
Increment = lambda { |number| number + 1 }
Use {} for single line lambdas and do..end for lambdas that are longer than a single line.
[1,2,3,4,5].each{ |num| puts num**2}
# OR
[1,2,3,4,5].each do |num|
puts num**2
end
Written on July 10, 2013