塊
塊是大括號 {}
(通常用於單行塊)或 do..end
(用於多行塊)之間的程式碼塊。
5.times { puts "Hello world" } # recommended style for single line blocks
5.times do
print "Hello "
puts "world"
end # recommended style for multi-line blocks
5.times {
print "hello "
puts "world" } # does not throw an error but is not recommended
注意:大括號的優先順序高於 do..end
生產
可以使用單詞 yield
在方法和函式內部使用塊:
def block_caller
puts "some code"
yield
puts "other code"
end
block_caller { puts "My own block" } # the block is passed as an argument to the method.
#some code
#My own block
#other code
但要小心,如果在沒有阻擋的情況下呼叫 yield
,它會產生一個 LocalJumpError
。為此,ruby 提供了另一種名為 block_given?
的方法,它允許你在呼叫 yield 之前檢查塊是否已通過
def block_caller
puts "some code"
if block_given?
yield
else
puts "default"
end
puts "other code"
end
block_caller
# some code
# default
# other code
block_caller { puts "not defaulted"}
# some code
# not defaulted
# other code
yield
也可以為塊提供引數
def yield_n(n)
p = yield n if block_given?
p || n
end
yield_n(12) {|n| n + 7 }
#=> 19
yield_n(4)
#=> 4
雖然這是一個簡單的例子,但是 yield
ing 對於允許在另一個物件的上下文中直接訪問例項變數或評估非常有用。例如:
class Application
def configuration
@configuration ||= Configuration.new
block_given? ? yield(@configuration) : @configuration
end
end
class Configuration; end
app = Application.new
app.configuration do |config|
puts config.class.name
end
# Configuration
#=> nil
app.configuration
#=> #<Configuration:0x2bf1d30>
正如你所看到的,以這種方式使用 yield
使得程式碼比不斷呼叫 app.configuration.#method_name
更具可讀性。相反,你可以執行塊內的所有配置,保持程式碼包含。
變數
塊的變數是塊的本地(類似於函式的變數),它們在塊執行時死亡。
my_variable = 8
3.times do |x|
my_variable = x
puts my_variable
end
puts my_variable
#=> 0
# 1
# 2
# 8
塊無法儲存,一旦執行就會死亡。為了節省塊,你需要使用 procs
和 lambdas
。