Block
定义
some_array.each { |value| puts value + 3 }
sum = 0
other_array.each do |value|
sum += value
puts value / sum
end
- A block is somewhat like the body of an anonymous method
- Block can take parameters
- Block 只有被 method 调用时才会起作用,如果 method 中有参数,block 出现在最后面
Block 中的变量
如果 block 的本地变量的名字和 block 之外但是在同样 scope 里面的 变量名字一样,那他们两个是一样的。block 内变量的值会改变 block 外变量的值。
sum = 0
[1,2,3,4].each do |value|
sum += value
puts value / sum
end
puts sum # => 30
如果 block 中的变量只出现在 block 中,那么它只是 block 中本地变量,无法在 block 之外被引用。
sum = 0
[1,2,3,4].each do |value|
square = value * value
sum += square
end
puts sum # => 30
puts square # undefined local variable or method 'square' for main:Object NameError>
Parameters to a block are always local to a block, even if they have the same name as locals in the surrounding scope.
value = "some shape"
[1,2].each { |value| puts value }
puts value
# 1
# 2
# some shape
You can define a block-local variables by putting them after s semicolon in the block's parameter list
square = "some shape"
sum = 0
[1,2,3,4].each do |value; square|
square = value * value
sum += square
end
puts sum # 30
puts square # some shape
- By making square block-local, values assigned inside the block will not affect the value of the variable with the same name in the outer scope.
- Blocks for Transactions
- You can use blocks to define a chunk of code that must be run under some kind of transnational control
class File
def self.open_and_process(*args)
f = File.open(*args)
yield f
f.close
end
end
File.open_and_process("testfile","r") do |file|
while line = file.gets
puts line
end
end
Blocks Can Be Objects
You can convert a block into an object, store it in variables, pass it around, and then invoke its code later.
如果 method 的最后一个参数前面有 符号 (action), 那么当此 method 被调用时,Ruby 会找一个 code block, 这个 code block 被转换成 class Proc 的一个对象。
class ProcExample
def pass_in_block(action)
@stored_proc = action
end
def use_proc(parameter)
@store_proc.call(parameter)
end
end
eg = ProcExample.new
eg.pass_in_block { |param| puts "The parameter is #{param}" }
eg.use_proc(99)
# => The parameter is 99
def create_block_object(block)
block
end
bo = create_block_object { |param| puts "You called me with #{param}" }
bo.call 99 # => You called me with 99
bo.call "cat" # => You called me with cat
Ruby have two built-in methods that convert a block to an object: lambda and Proc.new
bo = lambda { |param| puts "You called me with #{param}" }
bo.call 99 # => You called me with 99
- Blocks Can Be Closures
- Closure: Variables in the surrounding scope that are referenced in a block remain accessible accessible for the life of that block and the life on any Proc object created from that block.
def n_times(thing)
lambda {|n| thing * n}
end
p1 = n_times(23)
p1.call(3) #=> 69
p2.call(4) #=> 92
def power_proc_generator
value = 1
lambda { value += value }
end
power_proc = power_proc_generator
puts power_proc.call # 2
puts power_proc.call # 4
lambda 表达式的另一种简写方式
lambda { |params| ... }
# 与下面的写法等价
-> params { ... }
# parmas 是可选的
proc1 = -> arg1, arg2 {puts "#{arg1} #{arg2}"}
proc1.call "hello", "world"
# => hello world
proc2 = -> { "Hello World" }
proc2.call # => Hello World
Block Parameter List
Blocks can take default values, splat args, keyword args and a block parameter
proc = -> a, *b, block do
puts "a = #{a.inspect}"
puts "b = #{b.inspect}"
block.call
end
proc.call(1,2,3,4) {puts "in block"}
# a = 1
# b = [2,3,4]
# in block
您可能感兴趣的文章:- Ruby中Block和迭代器的使用讲解
- 深入理解Ruby中的block概念
- Ruby中的block、proc、lambda区别总结
- Ruby中使用Block、Proc、lambda实现闭包
- Ruby中的block代码块学习教程