Basics of Ruby Programming.
Basics of Ruby Programming
Variables and Data Types:
In Ruby, variables don't have types; instead, objects have types. Variables simply reference objects. Here's an example:
```ruby
name = "John" # String
age = 25 # Integer
salary = 2500.50 # Float
is_student = true # Boolean
```
Operators:
Ruby supports various operators for arithmetic, comparison, logical operations, etc. Here's an example:
```ruby
Arithmetic operators
sum = 5 + 3 # 8
difference = 10 - 5 # 5
product = 4 * 6 # 24
quotient = 10 / 2 # 5
Comparison operators
is_greater = 10 > 5 # true
is_equal = 10 == 5 # false
is_not_equal = 10 != 5 # true
Logical operators
logical_and = true && false # false
logical_or = true || false # true
logical_not = !true
# false
```
Control Flow:
Ruby provides various control flow structures like if, elsif, else, case, while, until, and for loops. Example:
```ruby
# if, elsif, else
grade = 85
if grade >= 90
puts "A"
elsif grade >= 80
puts "B"
else
puts "C"
end
# case
fruit = "apple"
case fruit
when "apple"
puts "It's an apple"
when "banana"
puts "It's a banana"
else
puts "Unknown fruit"
end
# while loop
counter = 0
while counter < 5
puts counter
counter += 1
end
```
Loops:
Ruby supports various loop constructs like while, until, and for loops. Example:
```ruby
# until loop
counter = 0
until counter >= 5
puts counter
counter += 1
end
# for loop
for i in 0..5
puts i
end
```
Object-Oriented Programming (OOP) in Ruby:
Classes and Modules:
Classes are blueprints for creating objects, while modules are collections of methods and constants. Example:
```ruby
class Person
def initialize(name)
@name = name
end
def greet
puts "Hello, #{@name}!"
end
end
module MathHelper
def self.square(num)
num * num
end
end
```
#### Inheritance:
Ruby supports single inheritance where a class can inherit behavior from another class. Example:
```ruby
class Animal
def speak
"Animal speaks"
end
end
class Dog < Animal
def speak
"Woof!"
end
end
dog = Dog.new
puts dog.speak # Output: "Woof!"
```
#### Mixins:
Mixins allow classes to share behaviors without inheritance. They are implemented using modules. Example:
```ruby
module Jumpable
def jump
"Jumping high!"
end
end
class Rabbit
include Jumpable
end
rabbit = Rabbit.new
puts rabbit.jump # Output: "Jumping high!"
```
#### Encapsulation:
Encapsulation is the bundling of data with methods that operate on that data. Here's an example:
```ruby
class Car
def initialize(speed)
@speed = speed
end
def accelerate
@speed += 10
end
def brake
@speed -= 10
end
def current_speed
end
end
car = Car.new(0)
car.accelerate
puts car.current_speed # Output: 10
```
#### Duck Typing:
Ruby follows duck typing, which means the type or class of an object is less important than the methods it defines. If an object quacks like a duck, it's treated as a duck. Example:
```ruby
class Duck
def sound
"Quack!"
end
end
class Dog
def sound
"Woof!"
end
end
def make_sound(animal)
puts animal.sound
end
duck = Duck.new
dog = Dog.new
make_sound(duck) # Output: "Quack!"
make_sound(dog) # Output: "Woof!"
```
### Ruby Standard Libraries:
#### Core Libraries:
- Kernel: Contains core methods available globally.
- Enumerable: Provides collection-specific methods.
#### Enumerable:
The Enumerable module provides a set of methods to iterate over collections like arrays, hashes, etc. Example:
```ruby
numbers = [1, 2, 3, 4, 5]
# Using Enumerable methods
numbers.each { |num| puts num * 2 } # Output: 2 4 6 8 10
# Other Enumerable methods: map, select, reject, etc.
```
Let's dive deeper into the Enumerable module and explore various methods for arrays, hashes, and other enumerable objects:
### Enumerable Methods for Arrays:
#### each:
Iterates over each element in the array and yields it to the block.
```ruby
numbers = [1, 2, 3, 4, 5]
numbers.each { |num| puts num } # Output: 1 2 3 4 5
```
#### map:
Creates a new array containing the values returned by the block.
```ruby
squares = numbers.map { |num| num * num }
puts squares.inspect # Output: [1, 4, 9, 16, 25]
```
#### select:
Returns a new array containing elements for which the block returns true.
```ruby
evens = numbers.select { |num| num.even? }
puts evens.inspect # Output: [2, 4]
```
#### reject:
Returns a new array containing elements for which the block returns false.
```ruby
odds = numbers.reject { |num| num.even? }
puts odds.inspect # Output: [1, 3, 5]
```
#### reduce (or inject):
Combines all elements of the array by applying a binary operation, specified by a block or a symbol that names a method or operator.
```ruby
sum = numbers.reduce(0) { |acc, num| acc + num }
puts sum # Output: 15
```
#### any?:
Returns true if the block ever returns a value other than false or nil.
```ruby
has_negative = numbers.any? { |num| num < 0 }
puts has_negative # Output: false
```
#### all?:
Returns true if the block never returns false or nil.
```ruby
all_positive = numbers.all? { |num| num > 0 }
puts all_positive # Output: true
```
#### count:
Returns the number of items in enum through enumeration.
```ruby
count = numbers.count
puts count # Output: 5
```
### Enumerable Methods for Hashes:
#### each:
Iterates over each key-value pair in the hash and yields it to the block.
```ruby
ages = { "John" => 25, "Jane" => 30, "Doe" => 40 }
ages.each { |name, age| puts "#{name} is #{age} years old" }
# Output:
# John is 25 years old
# Jane is 30 years old
# Doe is 40 years old
```
#### map:
Creates a new array containing the values returned by the block.
```ruby
doubled_ages = ages.map { |name, age| [name, age * 2] }
puts doubled_ages.inspect
# Output: [["John", 50], ["Jane", 60], ["Doe", 80]]
```
#### select:
Returns a new hash containing key-value pairs for which the block returns true.
```ruby
adults = ages.select { |name, age| age >= 18 }
puts adults.inspect
# Output: {"John"=>25, "Jane"=>30, "Doe"=>40}
```
#### reject:
Returns a new hash containing key-value pairs for which the block returns false.
```ruby
minors = ages.reject { |name, age| age >= 18 }
puts minors.inspect
# Output: {}
```
#### each_key:
Iterates over each key in the hash and yields it to the block.
```ruby
ages.each_key { |name| puts name }
# Output:
# John
# Jane
# Doe
```
#### each_value:
Iterates over each value in the hash and yields it to the block.
```ruby
ages.each_value { |age| puts age }
# Output:
# 25
# 30
# 40
```
#### key?:
Returns true if the given key is present in the hash.
```ruby
has_jane = ages.key?("Jane")
puts has_jane # Output: true
```
#### value?:
Returns true if the given value is present in the hash.
```ruby
has_age_25 = ages.value?(25)
puts has_age_25 # Output: true
```
#### empty?:
Returns true if the hash contains no key-value pairs.
```ruby
empty_hash = {}
puts empty_hash.empty? # Output: true
```