Ruby Is Elegance

今天持續Ruby study,紀錄一下學習到的東西

Yield

讓自定義的method可以接受block, 在yield之後的code會等block內容跑完才接著跑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def block_test
  puts "We're in the method!"
  puts "Yielding to the block..."
  yield
  puts "We're back in the method!"
end

block_test { puts ">>> We're in the block!" }

#you can pass parameter too
def yield_name(name)
  puts "In the method! Let's yield."
  yield name
  puts "Block complete! Back in the method."
end

yield_name("samuel") { |a| puts "My name is #{a}."}

The output is

We're in the method!
Yielding to the block...
>>> We're in the block!
We're back in the method!

In the method! Let's yield.
My name is samuel.
Block complete! Back in the method.

Why Proc?

block can’t be saved to a variable and not a regular object. Proc keep your code reusable. With blocks you have to write your code out each time you need it. With proc, you write your code once. Proc is savable block.

1
2
3
4
5
6
7
8
9
10
floats = [1.2, 3.45, 0.91, 7.727, 11.42, 482.911]
round_down = Proc.new { |x| x.floor }
# & is used to convert round_down proc to block
ints = floats.collect(&round_down)  # [1, 3, 0, 7, 11, 482]

# you can call proc directly
round_down.call(10.45) # 10

# convert Symbol to Proc by &
puts floats.map(&:to_s)

Lambdas

lambdas are objects and identical to procs

1
2
3
strings = ["leonardo", "donatello", "raphael", "michaelangelo"]
symbolize = lambda { |x| x.to_sym }
symbols = strings.collect(&symbolize) # [:leonardo, :donatello, :raphael, :michaelangelo]

Differences between Procs and Lambdas

  1. Lambdas checks the number of arguments passed to it. Procs ignore it.
  2. When Lambdas returns, it passes control back to calling method. Procs doesn’t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def batman_ironman_proc
  victor = Proc.new { return "Batman will win!" }
  victor.call
  "Iron Man will win!"
end

puts batman_ironman_proc  # Batman will win!

def batman_ironman_lambda
  victor = lambda { return "Batman will win!" }
  victor.call
  "Iron Man will win!"
end

puts batman_ironman_lambda  # Iron Man will win!

Class

Object-Oriented language always has class. def initialize就相當於constructor

1
2
3
4
5
6
class Person
  def initialize(name)
      @name = name
  end
end
matz = Person.new("Yukihiro")

global ($), instance (@), class (@@) variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person
  $type = "human"
  @@other = "other info"
  def initialize(name)
      @name = name
  end
  def getMe
      @name
  end
  def self.getOther
      @@other
  end
end

man = Person.new("samuel")
puts $type  # human
puts man.getMe  # samuel
puts Person.getOther  # other info

Inheritance

Like Java, Ruby only allow one parent class

1
2
3
4
5
6
7
8
9
10
class Parent
  def isMankind?
      true
  end
end
class Child < Parent
end

child = Child.new
child.isMankind  # true

Public and Private method

It’s very simple, put method declaration under public or private

1
2
3
4
5
6
7
8
9
class MyClass
  public
  def iampublic
  end

  private
  def iamprivate
  end
end

Method getter and setter

Incredible simple. attr_accessor means both writer and reader.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person
  class << self
    attr_accessor :is_good?
  end

  attr_reader :name
  attr_writer :job
  attr_accessor :age
  def initialize(name, job, age)
    @name = name
    @job = job
    @age = age
  end
end

Person.is_good?
person = Person.new("samuel","engineer",30)
person.name
person.age

Module

module is like class but it can’t create instance and submodule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module MyModule
  #constant variable
  NAME = "samuel"

  #class method
  def self.showFull
      puts NAME + " hung"
  end
end
# user :: to access variable
puts MyModule::NAME  # samuel
MyModule.showFull # samuel hung

# you can use include to get module scope
include MyModule
puts NAME # samuel
showFull  # this line will cause error, you can't do this on method even you change the scope.

# load other module to use
require 'date'
puts Date.today

Module and Class

Easily put module in class

1
2
3
4
5
6
7
8
9
10
11
module MyModule
  def showFull
      puts "samuel hung"
  end
end

class Person
  include MyModule
end
man = Person.new
man.showFull

Comments