Ruby是一個「物件導向」相當徹底的一門程式語言,幾乎所有的東西都是物件,例如:
為什麼說"幾乎"呢?
在寫各種迴圈的時候,會大量的運用到Block:
numbers = [1,2,3,4,5]
p numbers.map{|num| num * 2} #印出[2,4,6,8,10]
p numbers.select{|num| num.odd?} #印出[1,3,5]
p numbers.reduce(0){|accu,num| accu + num } #印出15
5.times { puts "Hello" } #印出5次Hello
numbers.each do |num|
num * 2 #印出[2,4,6,8,10]
end
在Ruby,{ ... }及do end就是Block,且前面要接一個method。
puts {"Hello, World!"} #會出現語法錯誤
sentences = {"Hello, World!"} #會出現語法錯誤
雖然Block不是物件,但Ruby有內建兩個方法可以使Block物件化。
ninjutsu = Proc.new {puts 'らせん(螺旋)がん(丸)'}
ninjutsu.call #印出 らせん(螺旋)がん(丸)
可以用call
的方式呼叫,且可以帶參數
#call方法呼叫
calculator = Proc.new {|num| puts num * 2}
calculator.call(5) #印出 10
#call()方法且帶參數呼叫
def sushi_plate(price)
return Proc.new {|num| num * price}
end
nigili = sushi_plate(50) #100
avacado = sushi_plate(30) #150
puts "Nigili is $#{nigili.call(2)} and avacado is $#{avacado.call(5)}."
#印出Nigili is $100 and avacado is $150.
==注意!!!==
Proc.new { return ... }
return請不要寫在Proc的Block裡,否則程式碼執行到這段後就會停止(return完後立即停止),不會繼續往下走。
def proc_airline
p "strat from TPE"
airline_proc = Proc.new { return "Eva airline" }
airline_proc.call
p "has arrived NRT"
end
p proc_airline
#印出"strat from TPE"
# "Eva airline"
#"has arrived NRT"不會印出,因為在第3行就停止了。
有點類似匿名函式
#方式一:
calculator = lambda {|num| puts num * 2}
calculator.call(5) #印出 10
#方式二:
calculator = -> (n) {puts n * 2}
calculator.call(5) #印出 10
這樣比較起來,兩個東西看起來真的非常相似,但他們之間還是有一點點的差異存在,我們來看以下例子:
若block預期有參數要帶入,Lambda的call不給參數會出現錯誤,Proc的call則不會出錯而是會回傳nil
lambda = -> (name) { puts "Hello #{name}" }
lambda.call("Ruby") #印出 Hello Ruby
proc = Proc.new { |name| puts "Hello #{name}" }
proc.call("Ruby") #印出 Hello Ruby
目前看起來都很正常,但再看下面:
lambda.call()
#出現error:wrong number of arguments (given 0, expected 1) (ArgumentError)
proc.call() #印出 Hello
Lambda函式若有預期要傳入參數但call卻沒有給的話,會直接跳出錯誤訊息,Proc後的call雖然也沒有給參數,程式還是可以過的,因為Proc會自動給nil
Proc的block裡若有return,會直接終止程式不繼續往下走,Lambda則不影響,會完整跑完程式。
def proc_pikachu
proc = Proc.new { return }
proc.call
p "使用鋼鐵尾巴!!"
end
proc_pikachu # 印不出 "使用鋼鐵尾巴!!"
def lambda_pikachu
lam = -> { return }
lam.call
p "使用鋼鐵尾巴!!"
end
lambda_pikachu # 印出"使用鋼鐵尾巴!!"
The difference between procs and lambdas is how they react to a return statement. A lambda will return normally, like a regular method. But a proc will try to return from the current context.The reason is that you can’t return from the top-level context.
from rubyguides
Block不是物件,不能獨立存在。
Proc可帶參數,要求有參數,call卻沒給參數時會回傳nil
,{return...}會跳出程式。
Lambda使用起來更像我們一般使用的method,且會嚴格要求參數數目,就算{return...}也會把程式跑完。
參考資料:
rubyguides
Modules in Ruby: Part II
What are Lambdas in Ruby?
Using Lambdas in Ruby
為你自己學Ruby on Rails
“Perseverance is not a long race; it is many short races one after another.”
– Walter Elliott, Clergyman
本文同步發佈於: https://louiswuyj.tw/