语法差异
- 块(block):
- 没有独立的定义语法,总是附属在方法调用之后。例如:
(1..5).each do |num|
puts num
end
- 通常用
do...end
或者{}
来表示。do...end
一般用于多行代码块,{}
一般用于单行代码块。
- Proc对象:
- 通过
Proc.new
或者lambda
关键字创建(虽然lambda
创建的严格来说是Proc
的子类Lambda
,但Proc.new
是最常见创建Proc
对象的方式)。例如:
proc_obj = Proc.new { |param| puts param }
lambda_obj = lambda { |param| puts param }
参数处理差异
- 块(block):
- 块没有自己独立的参数列表,它依赖于调用它的方法来传递参数。例如
each
方法传递给块的参数就是数组中的每个元素。
- 不检查传递的参数数量,即使方法传递的参数与块预期处理的参数数量不匹配,也不会报错(在方法内部会按照块的逻辑执行,多余参数会被忽略,缺少参数不会引发参数相关错误)。
- Proc对象:
- 定义时可以指定参数,调用时不严格检查参数数量。例如:
proc_obj = Proc.new { |a, b| puts a + b }
proc_obj.call(1) # 不会报错,b为nil
proc_obj.call(1, 2, 3) # 不会报错,3被忽略
- Lambda:
- 严格检查参数数量。如果传递的参数数量与定义时不一致,会抛出
ArgumentError
。例如:
lambda_obj = lambda { |a, b| puts a + b }
lambda_obj.call(1) # 抛出ArgumentError: wrong number of arguments (given 1, expected 2)
lambda_obj.call(1, 2, 3) # 抛出ArgumentError: wrong number of arguments (given 3, expected 2)
返回值差异
- 块(block):
- 使用
return
关键字会导致包含该块的方法立即返回,而不是块本身返回。例如:
def test_block
(1..3).each do |num|
return num if num == 2
end
return -1
end
puts test_block # 输出2
- Proc对象:
- 使用
return
关键字会导致Proc
对象所在的方法返回(和块类似)。例如:
def test_proc
proc_obj = Proc.new { return 10 }
proc_obj.call
return -1
end
puts test_proc # 输出10
- Lambda:
- 使用
return
关键字只会从lambda
表达式本身返回,不会影响外部方法。例如:
def test_lambda
lambda_obj = lambda { return 10 }
lambda_obj.call
return -1
end
puts test_lambda # 输出 -1