すべての出会いが美しいとは限らない。すべての別れが悲しいとは言えない。

0%

【Ruby】Block/Proc/lambda的区别

在Ruby语言中,Block 与 Proc 是不同的概念。而 Proc 和 lambda 虽然都是 Proc 对象,在进行处理时会有若干差别。

Block 和 Proc.new

Block 是代码块,而 Proc 是对象。参数列别中最多只能有一个 Block ,但是可以有多个 Proc 或 Lambda。

Block 是指通过 do~end 或 {} 来进行传递的参数,通常与 yield 来搭配进行使用。
例如:

1
2
3
4
5
6
def method_block
yield
end

method_block { p "block" }
#=> "block"

将 Block 进行对象化就是 Proc.new 。
Proc 对象一般通过 call 方法来进行调用:

1
2
3
4
5
6
7
def method_block(&block)
block.call
end

method_block { p "block" }

#=> "block"

Proc.new 使用参数的情况:

1
2
3
proc = Proc.new{ |a| p a * 2 }
proc.call(2)
#=> 4

Proc.new 和 lambda

lambda 函数是用于生成 Proc 对象的函数,与 Proc.new 一样通过 call 来进行调用。

1
2
3
4
5
6
7
8
def method_lambda
lambda1 = lambda{ p "lambda" }
lambda1.call
end

method_lambda

#=> "lambda"

但与 Proc.new 相比,两者有两点不通

参数数目

lambda 会检查参数的个数,如果参数个数与规定参数个数不同的情况下,lambda 会报错。而 Proc.new 则不会进行参数检查。
Proc.new的情况:

1
2
3
proc = Proc.new{ |a,b,c| p "#{a},#{b},#{c}"  }
proc.call(2, 4)
#=> 2,4,nil

lambda的情况下:

1
2
3
lambda1 = lambda{ |a,b,c| p "#{a},#{b},#{c}"  }
lambda1.call(2, 4)
#=> wrong number of arguments (2 for 3) (ArgumentError)

return 与 break 等关键字的执行

Proc.new的情况下:

1
2
3
4
5
6
7
def method_proc
proc = Proc.new { return p "proc" }
proc.call
p "method_proc"
end

#=>"proc"

lambda的情况下:

1
2
3
4
5
6
7
8
9
10
def method_lambda
lambda1 = lambda{ return p "lambda" }
lambda1.call
p "method_lambda"
end

method_lambda

#=>"lambda"
# "method_lambda"

Proc.new 的情况下, return 会从函数自身 method_proc 中跳出。而 lambda 则会回到 method_lambda 中。